How a seat works
A hundred seats of private inference on Robinhood Chain. Each seat is a Venice key with a daily cap paid by the coin's trading tax. What the keys leave unspent buys $QUOTUM at the 20:00 UTC bell and burns it, where the price guard allows.
- Cap
- The most a seat's key can spend in one session, in dollars. Set at the open as the smallest of three numbers: $50, 60% of the last 24 hours of trading tax divided by the seats live at the open, and 0.25% of the supply at the previous session's average price. Not a grant: what is not spent does not carry over.
- Seat key
- The Venice API key a seat holds while it holds the stake, for private and anonymized models, the label shown before sending. Put it in any app; the keeper meters it and never sees a prompt.
- Bell
- 20:00 UTC every day. The keeper counts each key's spend and reports it on chain; with the unspent part it tries to buy QUOTUM and burn it, where the price guard allows. A refused buy stays in the sink.
- Sink
- The contract that receives the coin's trading tax. It forwards what the seats spent to the payment address, and uses the unspent for the guarded buy and burn at the bell. A refused buy stays there. It has no admin withdraw path.
- PAYG
- Pay as you go: a prepaid project balance in USDG with its own API key, for agents without a seat. Separate from the seats and their caps.
Make a model call§
Use a seat key or a PAYG project key. Choose the key you have.
Seat key
Copy your key from Your seat, or take a seat. Calls spend the daily seat allowance directly at Venice. Set base_url to https://api.venice.ai/api/v1.
Set the environment variable, then run this cURL request. It prints the provider's JSON reply.
export QUOTUM_SEAT_KEY="your seat key"
curl https://api.venice.ai/api/v1/chat/completions \
-H "Authorization: Bearer $QUOTUM_SEAT_KEY" \
-H "Content-Type: application/json" \
-d '{"model":"deepseek-v4-pro","messages":[{"role":"user","content":"hello"}],"max_tokens":256}'For Python, run python3 -m pip install openai, save this as seat-call.py and run python3 seat-call.py in the same shell.
import os
from openai import OpenAI
client = OpenAI(
base_url="https://api.venice.ai/api/v1",
api_key=os.environ["QUOTUM_SEAT_KEY"],
)
r = client.chat.completions.create(
model="deepseek-v4-pro",
messages=[{"role": "user", "content": "hello"}],
max_tokens=256,
)
print(r.choices[0].message.content)Expect a greeting. The wording varies. cURL returns it in choices[0].message.content; Python prints it. The provider meters the call against the daily seat allowance, not a PAYG project balance. Find the seat receipt.
PAYG project key
Create a project key in PAYG with an approved wallet and funded project. No seat is required. Its base_url is https://quotum.org/api/payg/v1. Calls spend the prepaid project balance, within the key budget.
Set the environment variable, then run this cURL request. It prints the reply and billing JSON.
export QUOTUM_PAYG_KEY="your project key"
curl https://quotum.org/api/payg/v1/chat/completions \
-H "Authorization: Bearer $QUOTUM_PAYG_KEY" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{"model":"deepseek-v4-flash","messages":[{"role":"user","content":"hello"}],"max_tokens":256}'For Python, run python3 -m pip install openai, save this as payg-call.py and run python3 payg-call.py in the same shell.
import os
import uuid
from openai import OpenAI
client = OpenAI(
base_url="https://quotum.org/api/payg/v1",
api_key=os.environ["QUOTUM_PAYG_KEY"],
max_retries=0,
)
r = client.chat.completions.create(
model="deepseek-v4-flash",
messages=[{"role": "user", "content": "hello"}],
max_tokens=256,
extra_headers={"Idempotency-Key": str(uuid.uuid4())},
)
print(r.choices[0].message.content)
bill = r.quotum_billing
print(bill["id"], f"${bill['charge'] / 1e9:.6f}")Expect a greeting, then a receipt ID and the actual dollar charge. Wording and cost vary. cURL returns choices[0].message.content and quotum_billing; Python prints them. This is expected output, not a recorded paid run.
Send a unique Idempotency-Key per logical request. Reuse it only to retry that request. A duplicate returns its receipt and duplicate_response, without output replay or a second inference. Python disables SDK retries with max_retries=0. Read the PAYG limits and error behavior.
Check a receipt
For PAYG, find quotum_billing.id in the response. Read https://quotum.org/api/payg/v1/receipts/<id> with the same project key as a bearer token. charge is in billionths of a dollar, so divide by 1e9. The same key reads the project's whole history, pages of 50 over up to 92 days, at https://quotum.org/api/payg/v1/receipts?from=<ms>&to=<ms>, and the same rows as a file at https://quotum.org/api/payg/v1/receipts/export?format=csv&from=<ms>&to=<ms>; on /payg the cabinet shows them under History and saves the CSV with Export. Project balance and key budget are separate from the seat session cap.
For a seat, open Your seat and choose Receipts, or read https://quotum.org/api/receipts?session=N for the session's provider-reported spend per seat. Direct Venice calls count toward that spend but are absent from the metadata-only console call journal. Verify the receipt hash against the chain event.
1The seat§
v0.17, updated Oct 2A seat is one wallet holding 0.25% of the supply in the staking contract, and it carries one key. A hundred seats, a queue after them. Unstake at any time and the stake comes back, nothing else.
| What | How much | Who sends it | Where to check |
|---|---|---|---|
| Stake | 0.25% of the supply, 2,500,000 QUOTUM | Your wallet | QuotumStaking 0x7F1d…7A53 |
| Seats | A hundred, one per wallet. Then a queue | The contract | SeatTaken, SeatQueued |
| Leave | Unstake at any time. The key is deleted | Your wallet | SeatFreed |
| Idle | After two sessions at $0 with someone waiting, the seat goes to the queue and the stake stays | Keeper | Idle |
A seat is one wallet holding 0.25% of the supply of $QUOTUM in the staking contract. There are a hundred seats, one per wallet. The next wallet waits in a queue that the contract keeps and the page reads from the chain.
- Stake any amount at any time. The moment your stake crosses 0.25% of the supply you take the first free seat, or join the tail of the queue if all hundred are taken.
- Unstake at any time, mid-session included. If your stake falls under 0.25% the seat frees, its key is deleted, and the head of the queue takes the seat. Unstake returns the stake and nothing else. On the seat page, leave the seat does it in one transaction for the whole stake. It is simulated first, then the page shows the seat freed, the key deleted and the QUOTUM returned.
- Idle. A seat that spends nothing two sessions in a row goes to the queue if someone waits. The stake is not touched. You are moved to the tail and the next wallet is seated.
The staking contract has no owner, no pause and no withdraw path. The keeper can only mark idle seats and release them after two idle sessions, and only when someone waits in the queue.
Connect a wallet
Any browser wallet works, Rabby or MetaMask for example. Press Connect in the header: the wallet shares its address and nothing is signed. If the wallet holds a seat, the header shows its number and opens it. On a phone, open quotum.org in the wallet app's own browser.
The coin lives on Robinhood Chain, chain id 4663. When you take a seat the page asks the wallet to switch to it, and to add it first if the wallet does not know it. A signature comes only when you sign in to a seat, and it costs nothing and sends nothing.
Take a seat. The page can quote ETH for the needed QUOTUM, route ETH through NVDA to QUOTUM, return unused ETH and stake the QUOTUM. Leaving returns QUOTUM. If you already hold enough QUOTUM, approve the staking contract, then stake.
2The session§
v0.17, updated Oct 2A session runs from one 20:00 UTC bell to the next, every day, weekends and holidays included. The cap is set right after a bell and counted at the next one. The key never turns off.
The bell rings at 20:00 UTC every day, weekends and holidays included. A session runs from one bell to the next. The cap is set right after a bell and counted at the next one. The first session, on launch day, runs from the launch to that evening's bell, so the first burn is the same evening. The key never turns off.
One day, one bell, one burn.
3The cap§
v0.17, updated Oct 2A seat can spend the smallest of $50, its share of 60% of the last day's trading tax, and 0.25% of the supply in dollars. The sink sets it right after the bell from what the chain shows. It holds until the next bell.
| What | How much | Who sends it | Where to check |
|---|---|---|---|
| Ceiling | $50 a session | The sink | Open(session, capUsd, …) |
| Tax share | 60% of the last 24 hours of trading tax, divided by the seats live at the open | The sink | Open(…, tax24hUsd, liveSeats) |
| Seat value | 0.25% of the supply at the last session's average price | PriceObserver 0x8cBA…3d0D | The observer |
| Team share | 40% of every claim, OPS_BPS 4000, fixed at deploy | The sink | Claimed(nvda, ops) 0xC1Fe…2741 |
The cap per seat is the smallest of three numbers, computed by the sink right after the bell from what the chain shows:
cap per seat = min(
$50,
60% of the last 24h of trading tax
in usd / seats live at the open,
0.25% of the supply in usd
at the last session's
average price
)In words, a seat can spend at most fifty dollars a session. Never more than its share of the tax actually collected in the last day. And never more than the seat itself is worth. If no seat is taken at the open, the cap is worked out as if there were one. The cap is paid by the coin's trading tax of the $QUOTUM / NVDA pair on Pons, collected in NVDA. 40% of every claim goes to the team's ops wallet (fixed in the sink at deploy, OPS_BPS 4000, address below). The other 60% is what the seats' cap and the burn are made of. The page prints the tax, the seats and the resulting cap every minute. If the tax dies the cap prints $0 and the page says so.
Keys never get more than the contract holds. A seat taken after the open gets the cap, or what is left of the collected tax if that is less.
The first session, on launch day, gives every key the smaller of the cap and one hundredth of the collected tax, so a seat taken late gets the same as a seat taken early.
The team funds the first session with $·, and the leftover burns at the bell.
The number holds until the next bell. Dollars here are dollars of inference at the provider's prices, not a share price.
Displayed key caps are rounded down to a cent. tax24hUsd already counts only the seats' 60%, after the team's 40%. A homepage figure more than five minutes old shows when it was read and its age.
4The bell and the burn§
v0.17, updated Oct 2At 20:00 UTC every day the keeper writes each seat's spend on chain, then rings the bell. What the seats spent is owed to the inference provider and forwarded. What they did not spend buys $QUOTUM on the pair in one trade and burns it.
| Step | What happens | Who sends it | Where to check |
|---|---|---|---|
report() | Each seat's spend and leftover for the session, with the receipt's hash | Keeper 0xD6dD…B8c2 | Reported On the sink |
bell() | Adds up not spent = cap − spent over every live seat | Keeper | Bell On the sink 0x42Ab…53a2 |
| Buy and burn | The NVDA behind the leftover buys $QUOTUM on the pair and the token's own burn() destroys it | The sink, in the bell tx | Burned, the token's total supply |
| Price guard | No buy above the pair's time-weighted price plus 10% and the pair's fees | The sink | Died With the reason |
forward() | The spent cap's NVDA goes to one published payment address, then to the provider | Keeper | Payment address 0x8a8F…6234 |
The bell, in order
- At 20:00 UTC the keeper calls
report()for every live seat with what it spent and did not spend, read from the provider's usage of that seat's key, with the hash of the seat's receipt row. - It calls
bell(). The sink adds up not spent over every live seat. - The NVDA behind that sum buys $QUOTUM on the pair in one trade, and the token's own
burn()destroys it. The supply drops by exactly the tokens in theBurnedevent, with the dollars, the NVDA and the average price beside them. - It buys only with NVDA the tax has already paid into the sink, after what is owed to the provider. A leftover with no NVDA behind it, a leftover under one dollar, or a refused buy is emitted as
Diedwith its reason. The NVDA of a refused buy stays for the next bell. - The spent part is forwarded by
forward()to the payment address, which pays the provider. Every payment is posted with its tx on the front page and on /usage.
What the chain shows
- Each seat's spend and leftover, as
Reported - The bell, the buy and the burn, in one tx
- The supply after every bell
- Every forward to the payment address
What it does not
- The spend itself is the provider's usage of the key as the keeper reads it, and the chain cannot check it
- The step from the payment address to the provider is custodial. Every payment is posted with its tx
Trust boundary
The chain enforces the split and the burn. The sink has no withdraw path, and no seat ever receives a token. You trust the keeper for the spend figure it reports, and the payment address for paying the provider. Both are posted with their tx so a wrong number is visible the same evening.

5The key§
v0.17, updated Oct 2Each seat has one Venice key. It is issued once the seat is taken on chain, limited to the session's cap and deleted when the seat is freed. Use it in the seat console or in any OpenAI-compatible app. Day keys are gifts cut off it.
| What | How much | Who sends it | Where to check |
|---|---|---|---|
| Issued | After SeatTaken, for private and anonymized models | Keeper | The seat page |
| Limit | The session's cap | Keeper, at Venice | The meter |
| Console | Chat, image, video. Web search about $0.01 a question | The seat wallet signs in | The meter |
| Day keys | $0.10 to $5, up to ten a session, end at the bell | The seat holder | quotum.org/k/<code> |
| Lifetime | Renewed seven days before the 90-day limit | Keeper | The seat page |
What the console logs
- The wallet
- The model
- The cost of each reply
What it does not
- The prompt
- The reply
- Media prompts and output
One key per seat, bound to the seat's wallet. No key exists before the stake is confirmed on chain (SeatTaken). Then the keeper issues a Venice key for private and anonymized models. The key's limit is what the seat is issued for the session. When the seat is freed the key is deleted. Any OpenAI-compatible client works.
The console. On the seat page the seat wallet signs once and chats on the seat's own key, with an optional web search that lists numbered sources (a search adds about $0.01 a question). Standard console requests go through quotum with the key on our server. The server stores no prompt or reply text. Chat history stays in this browser, keyed to the seat and wallet. The call journal at /api/receipts/calls keeps time, seat, model, privacy label, cost and a hash of the provider request id, never text. Calls from external apps are not in that journal. The meter shows what the key used, what is left, and what burns at the bell. It is the keeper's own read of the key plus the exact cost of replies since, the same number the keeper reports at 20:00 UTC.
Images and video. Switch the seat console to image or video to make media on the same key. Image prices come from Venice's model list. Video uses a quote before it joins Venice's queue. The console polls quotum for the finished video, then shows a download link. Each cost enters the seat meter when Venice accepts the request. Private and anonymized labels apply to media too. Prompts and output are not saved on our box.
The key in other apps. For Hermes, OpenClaw, Goose, Open WebUI or plain curl, the seat page shows each config with the key masked. Sign with the seat wallet, press copy, and the filled config goes to your clipboard. After a wallet signature, Apps and the day-key page can show or copy the raw key for 60 seconds, then wipe it from the tab. It is never written to browser storage, the URL or logs.
Day keys. A seat holder can split a day key from today's key, $0.10 to $5 and up to ten a session, and send the link quotum.org/k/<code>. Whoever opens it gets a Venice key until the next 20:00 UTC bell, a chat on the page and the Hermes / OpenClaw config by copy. The seat key's limit drops by the same amount in the same step, so the seat and its day keys together never pass the seat's allowance. What a day key spends is in the seat's receipt, and after the bell the day keys are deleted. Day keys are free and not for resale, and nothing sells a key. A seat gifts its day keys to builders from its own cap.
Key lifetime. A key lives 90 days at the provider. Seven days before that the keeper makes the seat a new key with what is left of the session's allowance, carries over what the old key spent, and deletes the old key. The meter and the bell do not move. Copy the config again once the seat page says the key was renewed.
# the key is a venice key: venice's own endpoint
from openai import OpenAI
client = OpenAI(
base_url="https://api.venice.ai/api/v1",
api_key="your seat key",
)
r = client.chat.completions.create(
model="deepseek-v4-pro",
messages=[{"role": "user", "content": "..."}],
)
# receipt: tokens in, dollars out. nothing else is kept.On private models Venice keeps no prompt or response. Anonymized models are Claude, GPT and Gemini run through Venice. The model provider does not know who you are but sees the prompt. Venice keeps key id, timestamps, model and token counts for billing. The model list with prices is below. When the cap is spent the key answers 402 until the next open.
Choose text, image or video in the composer menu. E2EE has its own switch. Video accepts an image as input and is quoted before dispatch. Replies have copy, text copy and rerun on another model, with sources, elapsed time, tokens and cost. A failed send keeps the question.
A reply shows thinking seconds while the model reasons. A stream silent for 90 seconds closes with the text received, including the final chunk. Switching wallets stops the stream and keeps the draft question. Long chats send the question, last answer and earlier turns that fit; the reply footer says how many older turns were omitted.
After installing an app config, send one prompt and open Check it worked. Compare its last observed spend and time with your request, or use the authentication help. Apps also shows the last spend seen and day-key counters; Receipts lists recent sessions.
Under Tasks, schedule a daily brief on a topic at the hour you choose, or the 19:30 UTC spend note. Latest runs appear in the console and linked Telegram chat. The built-in brief searches with the current date and lists sources, preferring Kimi K3, then Grok 4.7 and DeepSeek V4 Pro. It is separate from the downloadable DeepSeek morning-digest profile.
The seat's Record tab shows seals, tier progress, how many wallets hold each seal, the checked root and a share card. Copy the wallet address there, save the share card or copy it as an image with a link to the public record. Held secret seals show their name and icon; undiscovered ones stay locked.
/check reads Pons v2 launch facts free. An optional interpretation spends the seat key at the displayed current price. Recent checks stay only in this browser.
6E2EE§
v0.17, updated Oct 2In E2EE mode the seat console encrypts each turn in your tab to the key of the model's enclave and sends it from the tab straight to Venice on a small day key that lives in this tab. Quotum.org is not on the path. The tab checks the enclave before every turn and sends nothing if a check fails.
| Part | What it is | Who holds it | Where to check |
|---|---|---|---|
| Day key in this tab | A day key of the seat, $0.25 to $1, ends at the bell. What it did not spend goes back | This tab's memory only | The seat's day keys |
| Attestation | The enclave's TDX quote, fetched with a fresh 32-byte nonce | Venice, per model | /tee/attestation |
| Encryption | Secp256k1 ecdh, hkdf-sha256, aes-256-gcm. A fresh key pair for each message | The tab | E2ee.js |
| Signature | Venice's signature for the reply, and who signed it | The enclave or Venice's gateway | /tee/signature |
| Route | Every reply says E2EE, this tab to Venice | The console | Under each reply |
A turn, in order
- The tab asks Venice for the enclave's attestation with a fresh 32-byte nonce.
- It checks the answer in the tab (list below). One failed check and the turn is not sent, in the clear or otherwise. The model is marked not verified in the picker.
- It encrypts two messages to the enclave's key, the rules with the earlier turns quoted and the question. No assistant role is sent, the protocol would leave it in the clear.
- It posts them to
api.venice.aion the tab's day key, streams the reply back and opens it in the tab. A chunk that arrives in the clear cuts the turn. - After the turn the console can fetch Venice's signature for the reply and show who signed it, with the sha-256 of the bytes the tab sent and received.
What the tab checks
- Venice's own check of the enclave passes
- Our nonce came back
- The enclave's key is its signing address
- The TDX quote reads and has debug off
- The quote holds that address and our nonce
- The attested model is the model you picked
What it does not check
- The quote's Intel signature chain is Venice's word, and the console says so next to the model
- Which hardware Venice routes to beyond the quote
Trust boundary
Our server sees that a day key was split from the seat for this tab and what it spent, read once a minute. It does not see the model, the text or its size. Venice sees the day key, the model, the time and size of the turn, its tokens and cost, and the ip address of the browser that sent it. The text reaches it encrypted to the enclave. This page's code comes from quotum.org, and you can read e2ee.js and app.js.
Limits
- Streaming only. No web search, no files or images, no tools.
- The chat history stays in this browser, in the clear, as for text turns.
- Thinking stays encrypted until you open it in the tab. After a reload it cannot be opened, the turn's key lived only in memory.
- Venice allows about a dozen attestation reads a minute.
7Models and prices§
v0.17, updated Oct 2The key reaches Venice's private and anonymized models. On private models Venice keeps no prompt or reply. Anonymized models are Claude, GPT and Gemini through Venice, where the provider sees the prompt without your identity. Prices per 1M output tokens, read every hour.
On private models Venice keeps no prompt or reply. Anonymized models route Claude, GPT and Gemini through Venice. The provider sees the prompt without your identity. Today's cap buys · output tokens of deepseek-v4-pro per session.
Every text, image and video model a seat key can call, with its input and output price, is on quotum.org/models.
| Model | Privacy | List $/1M | Cap buys |
|---|---|---|---|
| · | |||
The list covers Venice's private and anonymized models in $ per 1M output tokens, read by the keeper every hour. The last column is what today's cap buys in that model's tokens.
The console's picks include Claude Sonnet 5.5, Grok 4.7 and GPT-6.1 Sol. The versions they replaced remain in the full catalog when Venice serves them. These picks are separate from the PAYG pilot list and the house board.
8Receipts and payments§
v0.17, updated Oct 2Two things are not on the chain, and the page says so. They are the spend per seat and the payment to the provider. Each seat's spend goes on chain as a hash in Reported, and every payment is posted with its tx.
| What | How much | Who sends it | Where to check |
|---|---|---|---|
| Receipt | One row a seat a session, its hash is keccak256 of the row's JSON without its hash field | Keeper | /api/receipts?session=N, Reported |
| Usage | The last 13 bells, and JSON | The page | /usage |
| Team share | 40% of every claim, in the claim tx | The sink | Claimed(nvda, ops) |
| Payment | What is owed, to one payment address, then the provider | Keeper, forward() | Forwarded 0x8a8F…6234 |
What the keeper can do
- Open a session
- Report spend
- Ring the bell
- Forward what is owed
- Release idle seats
What it cannot
- Move a stake
- Send NVDA anywhere but the payment address, the ops wallet (its fixed 40% of each claim) and the pair
quotum.org/usage leads with cumulative sink burns since launch. Its table and /api/usage.json show the last 13 bells with spend, burns and txs.
- Spend per seat comes from the provider's usage API. The keeper writes it with
report()asReported(session, seat, usd, receiptHash). The receipt file for a session is at/api/receipts?session=N, one row per seat;hashis keccak256 of the row's JSON without its hash field. Hash the row again and compare with the event. - Payments. The tax lands in a contract with no withdraw path. 40% of every claim leaves at once for the team's ops wallet. From the rest it forwards what is owed to one published payment address, which converts and pays the provider. Every payment is posted on the home page with its tx.
- The team's share. The team takes 40% of every claim, sent to one wallet fixed in the contract in the same transaction as the claim (
Claimed(nvda, ops)). From the seat sink, this is the only team share. PAYG has separate net-margin accounting and its own OPS allocation. Nothing else leaves the sink but the provider's payment and the bell's buy.
One custodial step
There is no trustless way to pay the provider yet. The step is one address, used for nothing else, and every hop is a tx you can open.
Spend by a seat that leaves before the bell stays in today's usage and receipts, labeled separately from the on-chain bell total. It is paid from the provider balance, outside the sink's bell. A provider reserve protects call and house costs. Spend below one cent reads under $0.01.
An unavailable keeper is not zero spend or an empty history. Retry a failed usage read. Each bell chart bar is its dollar cap split into spent and burned parts; the sink tile reports current backing and session coverage.
The deployer burned 28,604,787 QUOTUM on Sep 26 at 12:11 UTC. Its tx is linked on /usage; this was not a bell and is separate from the bell totals.
9Contracts§
v0.17, updated Oct 2Everything runs on four addresses on Robinhood Chain 4663: the coin, the staking contract, the sink and the price observer. The three of ours are immutable, with no owner and no admin withdraw. Sources verified on Sourcify.
Robinhood Chain, chain id 4663. QuotumStaking, TaxSink and PriceObserver are immutable, have no owner and no admin withdraw of any asset. Sources are verified on Sourcify in english.
| Contract | Role | Address |
|---|---|---|
| $QUOTUM | The coin, Pons v2, pair NVDA. Its trading tax goes to the sink. Listed on CoinGecko and DefiLlama | 0xFE93…018E |
| QuotumStaking | Stake, seats, queue, release | 0x7F1d…7A53 |
| TaxSink | Tax recipient. Cap, bell, burn, forward | 0x42Ab…53a2 |
| PriceObserver | Session twap of the pair, nvda/usd read | 0x8cBA…3d0D |
| Payment address | The bridge to the provider, used for nothing else | 0x8a8F…6234 |
| Ops wallet | The team's 40% of every claim, fixed in the sink | 0xC1Fe…2741 |
Events the page reads
Open(session, capUsd, tax24hUsd, liveSeats)Right after each bell. On launch day, at launchReported(session, seat, usd, receiptHash)Through the sessionBurned(session, usd, nvdaIn, tokens, twap),Died(session, usd, reason),Bell(session, spentUsd, burnedUsd)At 20:00 UTCForwarded(nvda)When what is owed leaves for the payment addressTransferTo the zero address on $QUOTUM, which is the burn itself, readable in any explorerSeatTaken,SeatQueued,SeatFreed,IdleFrom the staking contract
Fixed addresses
| Pons factory | 0x7eD5…EC7e |
| Pons escrow | 0xd3AF…Ac9e |
| NVDA | 0xd060…9EEC |
| Chainlink RHNVDA / USD | 0x379E…9F15 |
The observer builds its own time-weighted price from spot samples. Any wallet can call poke() once per block. If fewer than twelve samples cover the session the bell buys nothing and the leftover dies with the reason.
10Verify it yourself§
v0.17, updated Oct 2The seat key is Venice's own. Point any client at api.venice.ai with it, and nothing of ours sits in between.
The seat key is issued by Venice itself. The app configs point straight at api.venice.ai and not at us. Call the model list with your key and see what Venice serves you.
# your seat key, venice's own endpoint: nothing of ours in between
curl https://api.venice.ai/api/v1/models \
-H "Authorization: Bearer your seat key"The standard seat console passes the model name as is through quotum. E2EE instead encrypts in the tab and calls Venice directly after attestation checks, on a day key. It is streaming only, with no web search.
A wallet's record. node verify.mjs --record <address> rebuilds the seals from chain logs and bell receipts and checks the record, its hash and its proof against the root posted on chain after each bell. Look one up at quotum.org/record. The same page lists the top 25 or 50 wallets of the last root by seals held, then the highest tier, with the move since the root before (/api/record/top). The same seals and tier share a rank. A row opens that wallet's record, and a lookup shows where the wallet stands and what the next rank takes. A row notes bells held in a row from 7 (held means 250,000 QUOTUM or more at the bell), and "since bell 1" when the wallet has held at every bell.
The record tiers are Copper, Silver, Gold, Diamond and Olympian. Seals pay nothing and do not change a seat's cap. The top three wallets have plaques; Replay rebuilds the previous bell, 17 seal filters narrow the table, Rising lists wallets that climbed, and the lookup shows what the next rank needs.
11The call for agents§
v0.20, updated Oct 6An agent reads call.json, drafts the number and the text. The seat wallet signs and sends it. An MCP server in one file reads the same JSON.
This section is about the call. To run an agent on a seat key or a day key, start from quotum.org/setup.
The call is one number a seat seals before the NYSE open, a guess at what the Chainlink RHNVDA/USD feed on Robinhood Chain 4663 reads at the 20:00 UTC bell. It stays sealed until the bell, then it is open to every reader to check. The call is a number. It is not advice. An agent can read, compute and draft the call. The seat wallet signs it. An agent never holds the wallet.
Read. GET https://quotum.org/api/call.json, any origin, not cached. now.session is the open session, now.day the day of the bell, now.openAt the deadline, now.accepting says whether calls are taken right now. The feed is feed.address, 8 decimals. It moves in steps of about 0.5%.
Write and sign. One line, single spaces. The price in USD with exactly two decimals, 1.00 to 10000.00. The salt 32 fresh random bytes as 0x and 64 lowercase hex, a new one every call, or the number could be guessed from the hash. Sign the line with the seat wallet, personal_sign (eip-191).
# the text the seat wallet signs
quotum.org forecast <session> <price> <salt>
# then one POST, content-type application/json
POST https://quotum.org/api/call
{"wallet": "0x…", "session": "6",
"price": "228.90", "salt": "0x…", "sig": "0x…"}
# answer: {seat, hash, sealedAt, how, spentUsd}
# one call a seat a session, no edits, no cancelKeep the salt and the text. The hash is keccak256 of the whole text in utf-8. It is how you check your own call later without trusting us. The deadline is the NYSE open of the bell day, 13:30 UTC under EDT and 14:30 UTC from 2 Nov. Trading days only. Weekends and NYSE holidays have no call, the bell still burns.
| When | Public |
|---|---|
| Sealed, before 20:00 UTC | The seat, the hash, the sealed time. The report() tx once it carries the hash on chain, within minutes of the seal |
| From 20:00 UTC | The number, the salt, the signed text, the signature, what the asks behind it cost, the miss in basis points |
| Scoring | The last feed round at or before 20:00:00 UTC that day, from that day, above 0. With no such round the day is void and nothing is scored |
The house board. On some days the keeper also asks a few private Venice models for the same number, paid by quotum, with web search. Each answer is sealed like a seat call under its own text, quotum.org forecast-house <session> <model> <price> <salt>, signed by the keeper. House rows sit apart from the seats (house in call.json) and open at the same bell. No ranking of the models before 20 revealed sessions.
The reference runner. One house row, ensemble-v0, is not one model. Two researchers write a brief, one with live web and X search, one with web search. Five forecasters call from it, a critic reads their five numbers without their names, and the five revise once. The sealed number is the median. A measured run cost about $1, paid by quotum, with the runner ceiling of $1.40, and its cost is on its row like any other. The runner is one file, MIT, at quotum.org/ensemble.mjs. Fork it and change the models.
The MCP server. One file, node 18 or newer, no dependencies, read only. It reads call.json and nothing else. No tool writes, signs or holds a key. It has three tools, call_sessions (the latest sessions, one line each), call_session (one session in full), call_how_to_seal (the text to sign with today's session filled in, the formats, the deadline).
# the server is one file, served here
curl -O https://quotum.org/call-mcp.mjs
# stdio: any client that starts a process
claude mcp add quotum-call -- node /path/to/call-mcp.mjs
# http: one server for several agents on the same machine
node call-mcp.mjs --http 8811
claude mcp add --transport http \
quotum-call http://127.0.0.1:8811/mcpCall.json. Version 1: fields are only added, never renamed. The last 30 sessions with a call, newest first; ?session=N for one.
| Field | What |
|---|---|
now | The open session, the day of its bell, the deadline, whether calls are taken; next when they are not |
feed, rules | The Chainlink feed on 4663 and its page. The rules above, in words |
sessions[].state | Open (calls taken), sealed (past the open), revealed (from the bell), void (no price that day) |
sessions[].calls[] | One row per seat with seat, how, hash, sealed time and receipt. From the bell it adds the number, salt, text, signature, spend and miss |
sessions[].house[] | The house board with model, hash and sealed time. From the bell it has the same fields as a seat call |
sessions[].open, .bell, .burn | From the bell, the feed at the open (a free copy to compare with), the round the calls are scored against, and the bell's buy and burn |
house | On, models, ranked, revealed sessions. From 20 revealed sessions a board by mean miss |
Check a call yourself. Hash a revealed row's text with keccak256 and it equals hash. Recover the signer of text from sig, and it is the seat wallet, or the keeper for runner and house rows. Open the receipt to find the report() that carried the hash, mined before openAt. Read the feed's rounds back to the last one at or before 20:00:00 UTC, and it is bell.
Call from your agent. An agent can call for its seat without the wallet. On the seat page, under the call, the holder picks Your agent, with the seat's Hermes key and signs once. The leave reads quotum.org call-leave <seat> agent on 0.00 <ts> and stays until the holder signs it off or leaves the seat. Then the agent sends its number with the seat's Hermes key, before the NYSE open, one call a session. The keeper checks the key and the leave, draws the salt and signs quotum.org forecast-agent <session> <seat> <price> <salt>.
# the seat's Hermes key is the only credential
POST https://quotum.org/api/call/agent
Authorization: Bearer <the seat's Hermes key>
{"session": "11", "price": "182.43",
"why": "gap holds into the close",
"steps": [["pre-market gap", 0.8], ["chips firm", 0.4]],
"up": "NQ holds", "down": "a soft print",
"usdReported": 0.97}
# answer: {seat, hash, sealedAt, how: "agent", text}What an agent call proves, and what it does not. The keeper signs it on the key's word. The key proves to us which seat sent it, and to nobody else, so we could have written the call ourselves. call.jsonl marks these calls keeper-agent, apart from calls a seat wallet signed. The cost on the row is the agent's own count, usdReported. Beside it sits usdKey, what the seat's agent keys had spent this session at the last read from Venice before the seal, with the time of that read. It includes anything else the key did that day. The keeper reads Venice every minute, and a failed read leaves the last good one, so check the time. The line, the steps and the cost ride beside the call but are not in the signed text, so nothing proves them except our word.
The line we hold ourselves to. Bell N is the first bell after agent calls go live. By bell N+7, at least three seats other than seat 1 must each seal a call that cost $0.50 or more by the agent's own count, at four or more of the seven bells N+1 to N+7. $0.50 is ten times seat 1's runner and half the reference runner. If they don't, the call goes back to seat 1's runner, we stop building on it and say so here and on the log. Nobody is paid, rewarded or airdropped for a call or a good score.
Or run the verifier. call.jsonl has one line for every revealed call, oldest first, with the receipt row that put its hash on chain. verify.mjs checks each line from a public RPC and trusts nothing of ours. It takes the day from the session on chain and the keeper's address from the sink, finds the Reported event that carries the row and checks it was mined before the deadline. Then it walks the feed's rounds and recomputes the miss. Calls sealed before the verifier shipped have no kept row, so their receipt check reads as incomplete, not passed.
# one line per revealed call, any origin, not cached
curl https://quotum.org/api/call.jsonl
# the verifier: node 20 or newer and viem
curl -O https://quotum.org/verify.mjs && npm i viem
node verify.mjs --session 11From session 11, revealed model calls include percentage moves and prices after each step. A rest row reconciles steps that miss the final number. Holder-authorized scheduled calls seal in the 12:30 UTC runner window before the NYSE open; giving leave does not seal immediately.
The house uses a separately budgeted day key cut from the ops seat. Code defaults include Kimi K3, Grok 4.7, GLM 5.3, DeepSeek V4 Pro, Qwen 3.8 and ensemble-v0. Read call.json under house.models for the enabled set. This budget is separate from the reference runner's own ceiling.
12Hermes§
v0.19, updated Oct 5Hermes Agent runs on a seat with the quotum provider plugin. hermes usage then shows the seat's cap, the spend, what is left and the 20:00 UTC bell. Spend is counted per key in public, prompts are not read.
Install. Get a Hermes key, or the seat key, from the seat page under Other apps with the seat wallet's signature. Then three lines.
hermes plugins install qvotvm/hermes-quotum --enable
echo 'QUOTUM_SEAT_KEY=<your key>' >> ~/.hermes/.env
hermes config set model.provider quotum && hermes config set model.default kimi-k3The Hermes key. On the seat page, under Other apps and Hermes, the seat wallet signs for one Hermes key and picks an amount, $1 up to the seat's cap. Each session the Hermes key gets that amount off the seat's cap. What it leaves unspent burns at the bell with the rest of the seat. Sign again to see the key again or to revoke it. A freed seat loses its Hermes key. Put the Hermes key in QUOTUM_SEAT_KEY in place of the seat key.
The plugin is open source, MIT, at github.com/qvotvm/hermes-quotum. Read it before you give it a key.
What goes where. Hermes sends prompts to api.venice.ai with the key. The plugin asks quotum.org for the meter with a short hash of the key, never the key itself or a prompt. The keeper counts spend per key hash, per day and per plugin version, and nothing else. The models are private and anonymized models on Venice. The terms apply to every key.
Seat 1 is the team's seat. Every other seat is a holder seat. Spend on seat 1 is ours and is shown apart from the rest in usage.json.
The line we hold ourselves to. Bell N is the first bell after the plugin is listed in the Hermes catalog, or after the repo has been live for seven days without a listing. By bell N+7, at least three seats other than seat 1 must each spend $1 or more through their Hermes key at four or more of the seven bells N+1 to N+7. If they don't, we stop promoting the plugin and say so on this page and on the log. The plugin stays up either way. Nobody is paid, rewarded or airdropped for using it.
The downloadable morning-digest setup reports a failed X API read as an error, not a quiet window.
13The mechanics§
v0.17, updated Oct 2The cap fills right after the bell, the bell counts what is left at 20:00 UTC, and what is left buys $QUOTUM on the pair and burns it.



14The measure§
v0.17, updated Oct 2The unit is $QUOTUM itself. Nothing is minted, there is no second token, and every burn is the token's own burn() with its event. The supply only goes down.

- The unit
- $QUOTUM itself. Nothing minted, no second token. What the seats did not spend by the bell buys $QUOTUM on the pair and burns it, so the supply only goes down.
- The ceiling
- A bell spends at most the unspent cap, and only the NVDA the tax already paid into the contract. It buys at the pair's price and refuses one more than 10% plus fees over the day's average.
- Burn()
- The token's own burn. The event Burned carries the dollars, the NVDA and the tokens, and totalSupply drops by exactly that. The home page reads both.
- Where it trades
- Graduated to its Uniswap v4 pool. The bell buys there. Pools others open are not ours.
15FAQ§
v0.17, updated Oct 2Short answers to what people ask most, such as whether the cap is real or a dividend, whether it can rug, where the tax goes and why the bell is at 20:00 UTC.
- Is there an airdrop or a claim?
- No. quotum has no airdrop, claim or eligibility check. Seats are only taken on quotum.org, and we never ask you to connect a wallet anywhere else.
- “The cap is fake, you'll stop topping it up.”
- The tax recipient is a contract with no withdraw path. 40% of every claim goes to the team's wallet, fixed at deploy and printed here. The rest forwards to one published payment address, every payment is posted with its tx, and the cap is a formula on this page. If the tax dies the cap prints $0 and the page says so.
- What does each privacy label mean?
- Private means Venice keeps nothing from the prompt or reply. Anonymized means Claude, GPT or Gemini runs through Venice. That provider sees the prompt but does not know who you are. Choose the label before sending.
- Is this a faucet?
- A faucet gives it away. A seat costs 0.25% of the supply and the cap is whatever the tax collected, at most $50. The key goes with the stake.
- Is it circular, or a vamp?
- One coin, one pair, one tax. Nothing is minted, nothing is paid out. The tax buys inference, and what the seats did not spend buys the coin and burns it. That is the whole loop.
- Is it a dividend or yield?
- Nothing is paid out. The seat gets a cap it can spend, and no token. What it does not spend is burned. Unstake returns the stake and nothing else. It is capacity to spend, and it pays no yield.
- Can it rug?
- The staking contract has no owner and no withdraw. The sink has no owner and no withdraw. Unstake works at any time. The coin's price can go to zero, but nobody can take the stake.
- Is supply locked?
- The launch share is burned, tx in the launch thread, and every bell burns more. The seats lock 0.25% each, by choice, and can leave any time.
- Where does the tax go?
- Into a contract. 40% of every claim goes to the team's ops wallet, at once. Of the 60% that stays, spent cap is forwarded to the payment address and buys inference, unspent cap buys $QUOTUM at the bell and burns it. All three are events on the home page.
- Why 20:00 UTC, and why every day?
- The chain is 24/7 and so is the key, so the bell is too, once a day with weekends included. The bell stays at 20:00 UTC all year. That is the NYSE close while New York is on summer time, and from 2 Nov the close moves to 21:00 UTC. The hour is fixed so a clock can be set by it, and it does not follow the market. A session is bell to bell.
- How big is a seat?
- 0.25% of the supply in the staking contract. A hundred seats. The next wallet waits in a queue that reads from the chain.
- What if nobody spends?
- Then the whole cap, as far as the tax paid for it, buys the coin and burns it. Nothing goes to the provider that session. The page shows it.
- What is it paired with?
- NVDA on Pons. The tax lands in NVDA. The cap is quoted in dollars of the provider, never in shares.
- Is there a demo?
- The key works from any OpenAI-compatible client. The snippet is above. The receipt shows tokens in, dollars out.
- Is this a clone of Aria or Venice?
- We are a customer of Venice. We did not fork a token. No bond, no second unit, no mint rate. The cap comes from the trading tax of one pair and is counted at 20:00 UTC, every day.
16Pay as you go§
v0.74, updated Oct 18PAYG is an optional pilot beside seats. One wallet prepays USDG, revocable agent keys spend it through an OpenAI-compatible endpoint, and every charge has a receipt.
- Status
- PAYG opened on Oct 17 2026 as an invite-only pilot. To join, reply to the launch post on X or DM @quotumorg and wait for approval. Send USDG only from an approved wallet while intake is open, never while closed or paused. Check the PAYG page and
/api/payg/v1/statusfor open intake and its decision time, T0 plus 14 days. After opening, an unavailable PAYG is reported as unavailable. - Funding
- Register one funding wallet through a fresh domain-bound wallet challenge. Direct USDG transfers on chain 4663 become spendable after 20 matching canonical blocks. Funding uses no deposit contract. Custody, refund and cancellation terms.
- Agent keys
- Revocable, spend-only project keys have model and daily limits. They default to 14 days, at most 30. A key serves the models picked when it was made. A model added later is not on older keys, so make a new key for it. Wallet-signed console sessions last at most 24 hours and have a $2 limit, raisable to $5.
- The call
- Set an OpenAI client's base_url to
https://quotum.org/api/payg/v1and send a uniqueIdempotency-Keyheader per logical request. Text-model function/tool messages only. Web search is off in the pilot. Image, video, TTS and embedding endpoints are outside the published text pilot. Duplicate requests return a receipt andduplicate_response, without output replay or a second inference.POST /api/payg/v1/chat/completions Authorization: Bearer <local project key> Idempotency-Key: <unique request id> { "model": "openai-gpt-6-luna", "messages": [ { "role": "user", "content": "hello" } ], "max_tokens": 256, "stream": true } - Reads
GET /modelslists fresh prices and privacy labels,GET /meterreads available and held prepaid balance, andGET /receipts/<id>reads durable billing.- Units
- Charges and meter values use integer USD nanodollars. Divide by 1,000,000,000. USDG transfers use six decimals.
- Price
- Actual USD plus DIEM provider cost is marked up 25%, bounded by the admitted hold and $0.25 per request. Both prompt/tools and output/reasoning enter the bound.
- Input limit
- Input is counted in bytes, not tokens. The count is the UTF-8 bytes of the canonical JSON of messages, tools and tool_choice, plus 512, plus 256 per message, plus 1,024 if tools are sent. The limit is 8,192 bytes, or 32,768 if we turn long context on for that project. Under the 8,192 limit one plain message without tools fits about 7 KB of text. A request over the limit gets 400
input-limitand nothing is charged. - Holder access
- A wallet with at least 0.1% of QUOTUM supply, counting QUOTUM staked in its seat, can enroll with no invite. Its project can keep up to $100 unused instead of $50, and up to $200 from 0.5%. The balance is checked at enrollment and at each top-up against supply at that moment, so the token count moves as supply burns. Each top-up uses the cap of the tier the wallet is in at that moment, and $50 below 0.1%. Nothing is locked. It pays holders nothing; it only changes enrollment and the unused cap. Credited balance and withdrawals stay as they are.
- Privacy
- GPT-6 Luna, Mercury 3, MiniMax M3.1 Flash and Gemini 4 Argon are labeled anonymized in the Venice catalog. The other pilot models, Nemotron and Muse among them, are private. The gateway sees plaintext.
- Margin
- 60% of realized positive cumulative net PAYG margin, after refunds, supplier consumption, losses, measured expenses and reserves, funds a separate published wallet's 20:00 UTC QUOTUM buy and
burn(). 40% goes to OPS. - Burns
- PAYG burns have not started yet. Until they do, that 60% waits in the ledger as allocated batches. Unknown costs and unused deposits contribute no burn margin. A paid request shows $0 for the buy and burn on its receipt while PAYG's cumulative costs and reserves are still above revenue. There is no positive margin to split yet. Operator accounting and chain receipts stay separate from the seat bell.
Example
Python with the OpenAI SDK. Turn the SDK's own retries off: a resend with the same Idempotency-Key returns the receipt, not a second answer. Each answer carries its receipt in quotum_billing.
import uuid
from openai import OpenAI
client = OpenAI(
base_url="https://quotum.org/api/payg/v1",
api_key="your project key",
max_retries=0,
)
r = client.chat.completions.create(
model="deepseek-v4-flash",
messages=[{"role": "user", "content": "hello"}],
max_tokens=256,
extra_headers={"Idempotency-Key": str(uuid.uuid4())},
)
print(r.choices[0].message.content)
bill = r.quotum_billing
print(bill["id"], f"${bill['charge'] / 1e9:.6f}")The same request with curl. GET /receipts/<id> with the same key reads the receipt later.
curl https://quotum.org/api/payg/v1/chat/completions \
-H "Authorization: Bearer $QUOTUM_PAYG_KEY" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{"model": "deepseek-v4-flash", "messages": [{"role": "user", "content": "hello"}], "max_tokens": 256}'No seat is required. The text pilot allows at most $50 unused per project, $500 across projects and $0.25 per request. Funding requires an approved wallet and open intake. Unapproved or excess transfers stay held and can be requested back under the PAYG terms.
max_tokens is optional. The pilot defaults to and accepts at most 2048 output/reasoning tokens, bounded by the model's own limit; reasoning_effort is at most medium. Read /api/payg/v1/models for admitted limits, current prices and availability. The twelve pilot ids are gemini-4-argon, z-ai-glm-5-3-flash, zai-org-glm-5-2, openai-gpt-oss-120b, kimi-k3, deepseek-v4-flash, deepseek-v4-1-flash-1017, muse-spark-open, openai-gpt-6-luna, minimax-m3-1-flash, mercury-3 and nvidia-nemotron-3-5-super-vl-120b-a12b. An allowlisted id is not the same as a calibrated and available one: the models endpoint says which are live, and kimi-k3, muse-spark-open and gemini-4-argon are premium, priced above the rest. mercury-3 and minimax-m3-1-flash reason by default: with a small max_tokens the reasoning takes the whole budget and the reply comes back empty but charged (64 tokens asked, 61 went to reasoning, no text), so send "reasoning_effort": "none" or max_tokens of 512 or more. An explicit reasoning_effort needs a model that supports it; gemini-4-argon accepts the field only when it is left out.
Project keys may serve your own app's users under the PAYG terms; keep them on your server. This does not permit resale or sharing of raw gateway access or seat/day keys. Provider failure releases the charge; known client-cancellation work is charged. Unknown cost releases after 30 minutes without a later charge. Unused balance returns only to the funding wallet with a fresh signature, normally within 24 hours; withdrawals wait during reconciliation. x402 top-ups are later work.
17Pay from a wallet§
v0.87, updated Oct 20One model call, one USDG payment, no project and no key. A funded wallet signs a payment for a fixed text package and the answer comes back in the same exchange. It runs on the x402 pattern: the first request returns 402 with a quote, the second carries the signed payment.
- Packages
deepseek-v4-1-flash-1017at 0.003072 USDG andkimi-k3at 0.043200 USDG, each a fixed price for up to 4,096 input bytes including framing and 1,024 output tokens including reasoning. The charge is the package price: no balance, no change, no credit for what the answer did not use.GET https://quotum.org/api/payg/v1/request/packageslists the live packages and prices.- Pilot
- Settlement gas for the DeepSeek package is sponsored within a finite pilot budget, 100 settlements in all and 20 per UTC day. When it runs out, quotes for that package close. Kimi K3's price includes its own settlement.
- Payment
- USDG on Robinhood Chain (chain 4663), asset
0x5fc5360d0400a0fd4f2af552add042d716f1d168, six decimals. Bring an EOA wallet and an EIP-712 signer for a native USDG EIP-3009 authorization; contract wallets are not supported. Before signing, check the network, the asset, the payTo address and an explicit spend cap against the live quote. - The call
POST https://quotum.org/api/payg/v1/request/chat/completionswith an OpenAI-style body. The 402 answer carries a base64PAYMENT-REQUIREDheader and the same JSON body; a quote lasts 120 seconds. Resend the same body with the signed payment, base64 x402 v2, in thePAYMENT-SIGNATUREheader. The full contract is in openapi.json.- Answers
- 200 returns
choices,usageandquotum_billingwith the operation id, payment, fulfillment, amount, currency, accounting and the output's expiry. 202 carriesRetry-Afterand billing while payment, fulfillment or a refund is pending; a 202 is not proof of delivery or of a refund. A settled payment sent again returns 409payment_already_usedwithout output. - Recovery
- A plain HTTP client gets the response and nothing more: there is no automatic output recovery. A client that saves a 32-byte
X-Quotum-Recoverycapability before it sends, together withX-Quotum-Payerand a stableIdempotency-Key, can read the encrypted output for 24 hours:GET https://quotum.org/api/payg/v1/request/operations/<operationId>reads private billing, and/outputafter it returns the saved answer with theX-Quotum-Recoveryheader. Never publish that header or the buyer journal. Losing the capability means no automatic recovery. - Refunds
- Manually reviewed full refunds within 24 hours after a known failure, or after the 30-minute deadline for resolving an unknown outcome.
- Body commitment
- Optional extension
quotum-body-commitmentv1 in theX-Quotum-Body-Commitmentheader, a base64 JSON{version,message,signature}. The signature is EIP-712, domain{name: "Quotum Direct Body Commitment", version: "1", chainId: 4663}, primary typeDirectBodyCommitmentwith the fieldsresource(string),method(string),authorizationNonce(bytes32),bodyDigest(bytes32),package(string),quoteId(string) andexpiry(uint256, Unix seconds).bodyDigestis the 0x-prefixed SHA-256 of the canonical JSON body: object keys sorted recursively, array order kept. Sign it when the quote advertises it and keep both signatures before a retry. Once a claim was committed, a retry without the commitment is refused. - Privacy
- The gateway sees plaintext. Saved output is encrypted and kept for 24 hours.
Errors
- 400 request_invalid, payment_invalid, recovery_invalid, commitment_invalid.
- 404 route, operation_not_found. 405 method. 415 request_invalid.
- 409 authorization_order_conflict, quote_binding_conflict, payment_already_used, commitment_conflict.
- 410 quote_expired, output_expired. 413 work_bound_exceeded.
- 422 payment_invalid, payment_window, wallet_not_payable, token_paused, payer_frozen, insufficient_usdg, commitment_resource, commitment_nonce, commitment_body, commitment_quote, commitment_expired, commitment_window, commitment_signature, commitment_signer.
- 429 preflight_busy, preflight_limit, preflight_expired, quote_storage_limit, quote_limit, payer_limit.
- 503 price_stale, model_unavailable, sponsor_exhausted, settlement_unavailable, refund_gas_unfunded, refund_backing_shortfall, reservation_missing, resource_version_stale, chain_mismatch, token_domain_mismatch, intake_halted, supplier_capacity, tolerance_unbacked, refund_backing_unattested, loss_budget.
Example
Two requests with the same body. The first returns 402 and the quote in the PAYMENT-REQUIRED header. Check it, sign the USDG transfer it describes, and send the body again with the payment in PAYMENT-SIGNATURE. Node 20 with viem for the EIP-712 signature; any EIP-3009 signer works. The key comes from your own wallet setup, never from code.
import { privateKeyToAccount } from 'viem/accounts';
const account = privateKeyToAccount(process.env.BUYER_KEY);
const PAY_TO = 'the treasury address you verified'.toLowerCase();
const USDG = '0x5fc5360d0400a0fd4f2af552add042d716f1d168';
const url = 'https://quotum.org/api/payg/v1/request/chat/completions';
const body = JSON.stringify({ model: 'deepseek-v4-1-flash-1017', messages: [{ role: 'user', content: 'say hello in one sentence' }], max_completion_tokens: 1024, stream: false });
const json64 = (v) => Buffer.from(JSON.stringify(v)).toString('base64');
// 1. ask: 402 and the quote
const quote = await fetch(url, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body });
const required = JSON.parse(Buffer.from(quote.headers.get('PAYMENT-REQUIRED'), 'base64').toString());
const r = required.accepts.find((a) => a.network === 'eip155:4663' && a.asset.toLowerCase() === USDG);
// 2. check before signing: network, asset, payTo and your spend cap
if (!r || r.payTo.toLowerCase() !== PAY_TO || BigInt(r.amount) > 3072n) throw new Error('unexpected quote');
// 3. sign the USDG transfer authorization (EIP-3009) with the nonce the quote issued
const now = Math.floor(Date.now() / 1000);
const authorization = { from: account.address, to: r.payTo, value: r.amount, validAfter: String(now - 1),
validBefore: String(Math.min(now + r.maxTimeoutSeconds - 1, r.extra.quoteExpiresAt)), nonce: r.extra.authorizationNonce };
const signature = await account.signTypedData({
domain: { name: r.extra.name, version: r.extra.version, chainId: 4663, verifyingContract: r.asset },
types: { TransferWithAuthorization: [{ name: 'from', type: 'address' }, { name: 'to', type: 'address' }, { name: 'value', type: 'uint256' },
{ name: 'validAfter', type: 'uint256' }, { name: 'validBefore', type: 'uint256' }, { name: 'nonce', type: 'bytes32' }] },
primaryType: 'TransferWithAuthorization',
message: { ...authorization, value: BigInt(authorization.value), validAfter: BigInt(authorization.validAfter), validBefore: BigInt(authorization.validBefore) },
});
// 4. the same body again, with the payment
const payment = { x402Version: 2, accepted: r, resource: required.resource, payload: { signature, authorization }, ...(required.extensions ? { extensions: required.extensions } : {}) };
const answer = await fetch(url, { method: 'POST', headers: { 'Content-Type': 'application/json', 'PAYMENT-SIGNATURE': json64(payment) }, body });
console.log(answer.status, await answer.json());The same exchange with curl. curl does not sign: PAYMENT is the base64 payment from step 4 above, made by your signer. Send the identical body both times.
BODY='{"model":"deepseek-v4-1-flash-1017","messages":[{"role":"user","content":"say hello in one sentence"}],"max_completion_tokens":1024,"stream":false}'
# 1. the quote: 402, then read the PAYMENT-REQUIRED header
curl -si https://quotum.org/api/payg/v1/request/chat/completions \
-H "Content-Type: application/json" -d "$BODY" \
| grep -i '^payment-required:' | cut -d' ' -f2 | tr -d '\r' | base64 -d
# 2. the paid request, the same body
curl https://quotum.org/api/payg/v1/request/chat/completions \
-H "Content-Type: application/json" \
-H "PAYMENT-SIGNATURE: $PAYMENT" \
-d "$BODY"This is a plain client: keep the answer when it arrives. After an interruption, resend the same signed request unchanged; never sign a second payment for the same request. A settled payment sent again returns 409 payment_already_used without output, and a 202 means wait and read Retry-After, not pay again.
Machine-readable: openapi.json, the x402 manifest (quotum's own auxiliary manifest, not an x402 standard) and llms.txt.
