Tokenization
Tokenization on Provenance Blockchain is made simpler with NUVA Labs' APIs, which lets you create, manage, and transfer digital assets, including fungible tokens (e.g., RWAs - funds, policies, loans - stablecoins, utility tokens) and non-fungible tokens (NFTs).
This hub provides step-by-step workflows to:
- Mint a marker (a fungible token) that can be transferred and later traded.
- Create a scope (non-fungible asset) with a value owner and structured records, then enable transfers/trades.
- Build a lightweight "Asset Dashboard" that shows NAV, supply, balances, and holders for your assets.
What you'll build
- Mint & Transfer Fungible Tokens (Markers) → Create and manage fungible tokens with supply control, holder tracking, and transfer restrictions.
- Issue & Transfer NFTs (Scopes) → Create unique assets with metadata, ownership tracking, and data access controls.
- Build Asset Dashboard → Power dashboards with Plus aggregates: supply, holders, NAV, and transfer events.
Glossary: Key concepts
Fungible token A token that is interchangeable with others of the same type (e.g., stablecoins).
Marker Provenance's on-chain representation of a fungible token/denom with governance & permissions.
Restricted marker Marker that requires attributes or authority to transfer (see required_attributes)
Non-Fungible Token (NFT) A unique token representing ownership of a specific asset (e.g., real estate, art).
Scope A non-fungible, structured asset container (with Sessions & Records) in the Metadata module.
Denom A token identifier (e.g., nhash).
Data access: Addresses permitted to access scope-linked off-chain data.
Value owner Address registered as the owner of a scope's value; can be updated/transferred.
Plus endpoints (/v1) Curated, UI-ready aggregates for balances, metadata, transfers, NAV, holders, etc.
NAV Net Asset Value. Used for investor reporting and asset dashboards.
Get started
All calls use the same gateway and require:
| Authorization: Bearer <TOKEN> | Content-Type: application/json |
|---|
Operations on the API site are marked bearerAuth. Don't have a token yet? Use your tenant credentials or reach out to inbound@nuvalabs.com.
Base URLs
Declare bases so snippets are portable:
| # .env (example) | PROV_REST_BASE="https://api.provlabs.com" # Reads & writes (standard base) | PROV_PLUS_BASE="https://api.provlabs.com" # Plus aggregates live under /v1/... | PROV_VAULT_BASE="https://api.provlabs.com/vault" # Alternate mirror for the same writes | PROV_API_TOKEN="YOUR_TOKEN" |
|---|
How to submit writes (standard path)
- Direct POST (recommended) Call the documented operations on the standard base https://api.provlabs.com/.... This is the default, simplest path for licensed API integrations.
- Advanced (optional): Vault + RPC. If your custody model requires manual signing, build an unsigned tx with Vault, sign with your key/HSM/wallet, then broadcast via Node RPC. We don't cover that path here; reference only:
Node RPC broadcast (example)
curl -X POST -H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","id":1,"method":"broadcast_tx_sync","params":["<BASE64_SIGNED_TX>"]}' \
"https://pio-mainnet-1-rpc.provlabs.com"
Readiness checks
Run these against the address that will pay network fees for your writes:
- Service-sponsored: your service/treasury address is the fee-payer.
- User-pays: the end-user address is the fee-payer.
- Fee-grant: caller (grantee) has an allowance from a funded sponsor (granter).
Spendable (all denoms)
curl -H "Authorization: Bearer $TOKEN" \
"https://api.provlabs.com/cosmos/bank/v1beta1/spendable_balances/{address}"
Spendable (nHash)
curl -H "Authorization: Bearer $TOKEN" \
"https://api.provlabs.com/cosmos/bank/v1beta1/spendable_balances/{address}/by_denom?denom=nhash"
Fee-grant (granter → grantee)
curl -H "Authorization: Bearer $TOKEN" \
"https://api.provlabs.com/cosmos/feegrant/v1beta1/allowance/{granter}/{grantee}"
If your service submits on behalf of users Make sure fee-grants (and any signing grants) exist before tokenization writes. Grant creation is documented under Accounts → Permissions & Authorizations →; in this hub, we focus on tokenization flows.
If there's no balance and no grant: either fund the fee-payer or create a fee-grant (the grant-creation write flow is documented in Accounts: Permissions & Authorization →).
Pick a fee model
- Caller pays fees → caller must have spendable nhash.
- Sponsor pays (recommended for UX) → create a fee-grant from sponsor (granter) to caller (grantee); caller can submit writes with zero nhash. Verify with the fee-grant read above. (Plus "grantee/granter summary" endpoints exist on the API site if you need dashboard views.)
Common errors & troubleshooting
| Symptom / message | What it usually means | How to confirm | Typical fix |
|---|---|---|---|
| insufficient funds / insufficient fees | Fee-payer has no spendable balance nhash and no valid fee-grant | Check spendable balance and fee-grant | Fund fee-payer or create a fee-grant (granter→grantee) |
| missing required attribute (restricted marker) | Sender/recipient lacks a required attribute | Inspect marker required_attributes & account attributes | Add missing attribute(s) or use an eligible address |
| not authorized: ACCESS_* (e.g., ACCESS_MINT) | Caller lacks marker permissions | Check marker access control | Grant access (admin/mint/withdraw etc.) |
| marker not ACTIVE | Lifecycle incomplete | Get marker details (state) | Complete lifecycle before transfers |
| invalid bech32 | Malformed address | Validate address format | Use a valid tp1… / pb1… |