Bittensor SN25

Pay with Gamma

Buy UR Pro and data packs with SN25 gamma, entirely through the URnetwork API. The one step outside it is the mint you sign with your own coldkey.

What Gamma is

Gamma is a feature of the Bittensor chain, not an app or a wallet to install. Each subnet has its own gamma, and one gamma is worth one US dollar. You mint SN25's gamma with your coldkey into a deposit at a hotkey, and URnetwork spends from that deposit the price of what you buy.

Minting buys SN25 alpha with your TAO and burns it. URnetwork accepts SN25 gamma only.

Every other step is an API call, so a script or an agent can do all of it: read the terms, start a purchase, check its status and choose the automatic charges.

What you need

  • A URnetwork account, and a bearer token for it (step 1).
  • A Bittensor coldkey with enough TAO for the price and the transaction fee.
  • btcli, which comes with the bittensor Python package from version 11.3.2:
    pip install "bittensor>=11.3.2"

Step by step

Every call goes to https://api.bringyour.com. For every field and error, see the API reference.

  1. Get a bearer token

    Calls that need a token send it as Authorization: Bearer <token>. The token is a network JWT or an API key.

    Signing in gives you a network JWT, in network.by_jwt. For example, with a password:

    curl -X POST https://api.bringyour.com/auth/login-with-password \
      -H "Content-Type: application/json" \
      -d '{"user_auth":"me@example.com","password":"<password>"}'

    An API key works until you remove it. Create one with the JWT: it starts with urn_, and this answer is the only time you see it.

    curl -X POST https://api.bringyour.com/account/api-key \
      -H "Authorization: Bearer <network_jwt>" \
      -H "Content-Type: application/json" \
      -d '{"name":"gamma"}'
    { "id": "…", "api_key": "urn_…", "name": "gamma" }

    The settings in step 6 take a network JWT or an API key, and refuse a client JWT from POST /network/auth-client.

  2. Read the terms

    The terms need no token. They name the subnet, URnetwork's service hotkey and spender, each plan and data pack with its price in gamma and the daily cap a deposit needs for it, and whether minting works right now.

    curl https://api.bringyour.com/pay/gamma/terms
    {
      "available": true,
      "mint_available": true,
      "netuid": 25,
      "service_hotkey": "5CyQFykVpfa9xgZVGgBsiNUpjbo1EihBTSkPvDC1FZbL1wxG",
      "spender": "5EUQU938kFzJsVBjn9ch5RNNG4191j7mSz5Djf5vghrmWgUC",
      "max_price_age_blocks": 300,
      "min_mint_gamma": "0.1",
      "items": [
        { "plan": "monthly", "price_gamma": "5", "min_daily_cap_gamma": "5",
          "renews": true, "indicative_tao": "0.023645" },
        { "plan": "yearly", "price_gamma": "40", "min_daily_cap_gamma": "40",
          "renews": true, "indicative_tao": "0.189165" },
        { "item_id": "data_1tib", "price_gamma": "3", "min_daily_cap_gamma": "3",
          "renews": false, "indicative_tao": "0.014187" },
        { "item_id": "data_10tib", "price_gamma": "20", "min_daily_cap_gamma": "20",
          "renews": false, "indicative_tao": "0.094583" },
        { "item_id": "data_256gib", "price_gamma": "0.75", "min_daily_cap_gamma": "0.75",
          "renews": false, "indicative_tao": "0.003547" }
      ],
      "auto_min_daily_cap_gamma": "40",
      …
    }
    • available is false while purchases are off, and unavailable_reason says why.
    • mint_available is false while minting is off, and mint_unavailable_reason says why: gamma_disabled, subnet_gamma_disabled or price_stale. A deposit that already holds the price can still pay.
    • indicative_tao is about how much TAO a mint of the price takes: the chain's own simulation of the mint, plus 3%.
  3. Start a purchase

    Send the plan you want: monthly, yearly, or yearly_onboarding for the welcome offer while you can redeem it. For a data pack, send item_id instead: data_1tib, data_10tib, or data_256gib (256 GiB for $0.75, sold only with Gamma and over x402).

    curl -X POST https://api.bringyour.com/pay/gamma/intent \
      -H "Authorization: Bearer urn_..." \
      -H "Content-Type: application/json" \
      -d '{"plan":"yearly"}'

    To get a data pack as a balance code instead, add "delivery":"code". With an email, we email the code too.

    curl -X POST https://api.bringyour.com/pay/gamma/intent \
      -H "Authorization: Bearer urn_..." \
      -H "Content-Type: application/json" \
      -d '{"item_id":"data_1tib","delivery":"code","email":"me@example.com"}'

    The answer, for example:

    {
      "intent_id": "0b6f2f7e-4f1c-4a8e-9d1a-1f6a2b3c4d5e",
      "status_token": "<status_token>",
      "plan": "yearly",
      "amount_gamma": "40",
      "reference": "0x5d0c6b9e3e3c5c0a5b8f2a0f1d4a3e9b7c6d5e4f3a2b1c0d9e8f7a6b5c4d3e2f",
      "netuid": 25,
      "deposit_hotkey": "<deposit_hotkey>",
      "service_hotkey": "5CyQFykVpfa9xgZVGgBsiNUpjbo1EihBTSkPvDC1FZbL1wxG",
      "min_daily_cap_gamma": "40",
      "auto_min_daily_cap_gamma": "40",
      "min_mint_gamma": "0.1",
      "indicative_tao": "0.189165",
      "mint_available": true,
      "mint_dry_run_command": "btcli tx mint-gamma --netuid 25 --hotkey <deposit_hotkey> … --dry-run",
      "mint_command": "btcli tx mint-gamma --netuid 25 --hotkey <deposit_hotkey> … -w <your_coldkey>",
      "expires_at": "2026-11-12T12:00:00Z",
      …
    }
    • deposit_hotkey is the hotkey URnetwork assigned your account, on subnet 25. You mint into it, and it serves every later purchase too. It is not a pay-to address: never send TAO to it.
    • amount_gamma is the price in gamma, exactly what our spend takes. reference is this purchase's own 32-byte reference, which our spend carries on chain.
    • min_daily_cap_gamma is the smallest daily spend cap that lets this purchase be spent, and auto_min_daily_cap_gamma the smallest that lets every automatic charge be spent.
    • status_token reads this purchase's status. Keep it secret, out of URLs and logs.
    • If the mint fails with NonAssociatedColdKey, another coldkey already owns the deposit at that hotkey. Ask again with coldkey, the SS58 address of the coldkey you mint with, to get a hotkey it can use.
    • A purchase stays open until expires_at. Asking again for the same item returns the open purchase, with a new status_token.
  4. Mint gamma into your deposit

    Before you mint, read the caveats below.

    This is the one step outside the API, and the only signature. Preview the mint first: with --dry-run, btcli shows what you would get and submits nothing.

    btcli tx mint-gamma --netuid 25 --hotkey <deposit_hotkey> --amount-tao <TAO> \
      --service-hotkey 5CyQFykVpfa9xgZVGgBsiNUpjbo1EihBTSkPvDC1FZbL1wxG --dry-run

    Then mint, signed by your coldkey: the same command with -w <your_coldkey> in place of --dry-run. The purchase gives you both commands with your hotkey and an amount filled in, as mint_dry_run_command and mint_command.

    btcli tx mint-gamma --netuid 25 --hotkey <deposit_hotkey> --amount-tao <TAO> \
      --service-hotkey 5CyQFykVpfa9xgZVGgBsiNUpjbo1EihBTSkPvDC1FZbL1wxG -w <your_coldkey>

    --service-hotkey makes a new deposit name URnetwork's spender, and refuses a deposit that names another. Mint at least the price, about indicative_tao TAO; a mint smaller than min_mint_gamma gamma fails.

    You can also open the deposit with a daily spend cap, --daily-spend-cap-gamma <gamma>. Make it at least min_daily_cap_gamma, and at least auto_min_daily_cap_gamma if you keep the automatic charges. To change the cap later:

    btcli gamma set-cap --netuid 25 --hotkey <deposit_hotkey> \
      --daily-spend-cap-gamma <gamma> -w <your_coldkey>

    From Python, the bittensor SDK previews and makes the same mint:

    import asyncio
    import bittensor as bt
    
    async def main():
        wallet = bt.Wallet(name="<your_coldkey>")
        mint = bt.MintGamma(
            netuid=25,
            hotkey_ss58="<deposit_hotkey>",
            amount_tao="<TAO>",
            service_hotkey_ss58="5CyQFykVpfa9xgZVGgBsiNUpjbo1EihBTSkPvDC1FZbL1wxG",
        )
        async with bt.Subtensor() as client:
            plan = await client.plan(mint, wallet)  # the dry run: submits nothing
            print(plan.preview)
            await client.execute(mint, wallet)
    
    asyncio.run(main())
  5. Check the status

    Poll the purchase with its status_token; this call takes no bearer token. We credit a purchase only when our own spend carrying its reference is finalized on chain, never on the mint alone.

    curl -X POST https://api.bringyour.com/pay/gamma/status \
      -H "Content-Type: application/json" \
      -d '{"intent_id":"<intent_id>","status_token":"<status_token>"}'
    {
      "intent_id": "0b6f2f7e-4f1c-4a8e-9d1a-1f6a2b3c4d5e",
      "status": "paid",
      "amount_gamma": "40",
      "deposit_balance_gamma": "10",
      "remaining_gamma": "0",
      "spent_block": 9479641,
      "credited_at": "2026-11-11T12:01:12Z",
      …
    }
    pending
    No gamma at deposit_hotkey yet.
    seen
    The deposit holds gamma but can't pay yet: remaining_gamma is how much more to mint, or error.code says what stops the spend.
    confirming
    The deposit covers the price. Our spend is on its way, or it has landed and the credit is being written.
    paid
    Credited, on our finalized spend in block spent_block. A balance code is in balance_code.
    expired
    Nothing was spent before expires_at. Unspent gamma stays in the deposit for your next purchase.
    review
    Someone on our team is looking at it; review_reason says why.
    unknown
    No such purchase, or the token doesn't match.

    When the deposit can't pay, or the chain skips our spend, error.code says why:

    insufficient_gamma
    The deposit held less than the price. Mint more.
    daily_cap_too_low
    The deposit's daily cap is below the price. Raise it to at least min_daily_cap_gamma.
    daily_cap_exceeded
    Today's spends would pass the deposit's daily cap. Raise the cap.
    wrong_spender
    The deposit names another spender. Point it back at URnetwork's with the command below.
    btcli gamma set-spender --netuid 25 --hotkey <deposit_hotkey> \
      --service-hotkey 5CyQFykVpfa9xgZVGgBsiNUpjbo1EihBTSkPvDC1FZbL1wxG \
      -w <your_coldkey>
    no_deposit
    There is no deposit at the hotkey. Mint into deposit_hotkey.

    A skipped spend takes nothing and buys nothing. We try it again only after your deposit changes: when you mint more, raise the cap or fix the spender.

  6. Choose the automatic charges

    Paying with Gamma turns on automatic renewal and top-up for your account. Read and change them with a network JWT or an API key; a field you leave out stays as it is.

    curl https://api.bringyour.com/pay/gamma/settings \
      -H "Authorization: Bearer urn_..."
    
    curl -X POST https://api.bringyour.com/pay/gamma/settings \
      -H "Authorization: Bearer urn_..." \
      -H "Content-Type: application/json" \
      -d '{"auto_renew":false,"monthly_limit_gamma":"20"}'
    auto_renew
    At the end of each term of a plan paid with Gamma, charge the plan's price from the deposit, unless you pay for Pro another way past that term. A welcome-offer year renews at the yearly price. On by default.
    auto_topup
    When your data runs out, buy topup_item_id, at most once an hour. When a free account reaches its client limit, buy Pro, at most once a day; an automatic upgrade never changes how your network provides bandwidth. On by default.
    topup_item_id
    data_1tib, the default, data_10tib, or data_256gib.
    monthly_limit_gamma
    The most the automatic charges take in a calendar month, in UTC. "" or "0" removes the limit.

    Each automatic charge has its own reference and sends a receipt email. If the chain skips it, you get one notice, and it is tried again only after the deposit changes.

Before you mint

Gamma can't be refunded or transferred. We charge only the price of what you buy. Unspent Gamma stays in your deposit and works only on SN25.

Dissolving a subnet destroys its gamma.

Unless you turn them off, we charge the same deposit automatically: plans paid with Gamma renew at the end of each term, a data pack (1 TiB unless you choose another) is added when your data runs out, and a free account that reaches its client limit is upgraded to Pro.

  • Minting fails while the chain's TAO/USD price is more than 300 blocks old, about an hour. The terms then show mint_available as false, with price_stale. Pay with a coin or x402 meanwhile.
  • The deposit hotkey is not a pay-to address. Never send TAO to it. If you did, write to support@ur.io to have it returned.
  • A spend takes its whole amount or nothing, so a daily cap must be at least the price, and at least auto_min_daily_cap_gamma for the automatic charges. A deposit has no cap unless you set one.
  • A deposit and the coldkey that minted it are public on the chain.
  • Check that you pay URnetwork: btcli query services --netuid 25 lists SN25's services, and ours is the one marked owner.
  • Minting burns SN25 alpha. URnetwork receives no TAO.