Witbitz docs HomeTrustAll docs

The issuer — credit without accounts

There is a shorter overview of this at witbitz.chat/issuer — the same model with less API detail, including the honest-status table of what is live and what is not. This page is the one to integrate against.

Witbitz has no user accounts. Access is a link you hold; credit is a credential you hold. So who takes the payment, and how does the platform know what you paid for?

Someone else does. An issuer holds the customer, the payment relationship and whatever identity that requires. Witbitz validates and meters and knows neither. If that shape sounds familiar it is the one card networks use: your bank knows who you are, the merchant sees only that the payment cleared, and the scheme in the middle settles between them without holding either side's relationship.


The two sides of a tenant

A tenant sits on one side of the platform, or both:

role what it does
app builds a product on rooms, agents and collections, and spends credit
issuer holds the customer and the payment relationship, and funds wallets from its own prefunded balance

GET /v1/tenant reports your roles. They are set by an operator — a tenant cannot promote itself to issuer, because issuing is what turns a balance into spendable value.

A tenant created before roles existed reports roles: null and is treated as holding both, so nothing that worked before the split stopped working.

Issuers are prefunded. POST /v1/wallets/grant debits the issuer's own balance and returns 402 insufficient_credit when it is short. The platform never extends credit, which bounds what an issuer's failure can cost: users keep credentials already paid for, and nothing outstanding is at risk.

Epochs — a batch, not a purchase

Every credential names an epoch: the batch it was minted in, as an opaque id such as ep_47d5a543e80148deb604.

Credentials used to carry the issuing tenant id instead. Combined with a timestamp that identifies a specific purchase, and the metering ledger used to record which wallet paid for each call — so the two together reconstructed a path from who paid to what happened in which room. Both are gone: the ledger no longer records the wallet at all, and the tenant id became this batch id.

Epoch ids are random, never derived from the tenant. A derived id would be recomputable by anyone holding the tenant list, which would rebuild the link.

Publishing a batch

POST /v1/epochs          Authorization: Bearer wsk_…      (issuer role required)

{ "pub_key": "-----BEGIN PUBLIC KEY-----…", "cents_per_token": 25 }
→ 201 { "epoch": "ep_0158043c8123…", "cents_per_token": 25 }

Three rules worth knowing before you integrate:

You may name the epoch yourself if you need to mint tokens before publishing the key.

Redeeming

POST /v1/wallets/redeem

{ "token": "tok_…", "sig": "<base64url>", "epoch": "ep_…" }
→ 201 { "wallet_code": "WYZK-VG2M", "balance_cents": 25 }

The platform verifies your signature against that epoch's published key, records the token spent, and mints a wallet worth the epoch's denomination.

The wallet_code is shown once. It is a bearer credential: store it as the user's capability.

Blinding, and what is honestly true today

The design point of a token is that the platform can verify a credential without being able to link it to an issuance. That is what blind signatures give you: your client blinds a token, you sign the blinded value without seeing it, and the unblinded result is an ordinary signature. A verifier cannot tell it was produced blindly — which is exactly why Witbitz needs no special cryptography to accept one.

Two things are not true yet, and it would be dishonest to imply otherwise:

  1. Nothing here blinds anything. Blinding is your client's job and blind-signing is yours; neither lives in the platform. Until you do both, these are single-use bearer credentials with the right shape — not unlinkable ones.
  2. The epoch→issuer mapping is still held by the platform. It sits in its own row precisely so it can be moved out, but until it moves, Witbitz can still resolve which issuer minted a batch.

There is also a third link on the other path: credentials bought through Lemon Squeezy record the order id, so a purchased credential remains linkable to a buyer where a granted one no longer is. That is unavoidable while Lemon Squeezy is merchant of record and legally holds the buyer's identity anyway.

So the claim today is the smaller, real one: a granted credential can no longer be linked to a purchase. The larger claim — that the separation holds mathematically rather than organisationally — waits on blinding and on that mapping moving.

Settlement

Counts, not links. An issuer sells N tokens in an epoch; the platform redeems M of them; the issuer settles on M. Nobody needs to know which, which is what lets the books close while unlinkability is preserved. Double-spend is prevented by a permanent record of spent tokens — permanent deliberately, as an expiring record would make every token replayable once it lapsed.

Where this fits

Access is a link, credit is a credential, and identity belongs to whoever is willing to hold it. Witbitz holds neither your users' content nor their identity — which is the same argument as the double blind, applied to money instead of messages.

Machine-readable source: the-issuer.md · every doc in one fetch: llms-full.txt (HTML) · ← the-companion