Mint & Transfer Markers (Fungible Tokens)
Overview
Markers are fungible tokens on Provenance and represent interchangeable units of value (e.g., RWAs - funds, policies, loans -, stablecoins, utility tokens). In this workflow you will:
- Create a marker
- Verify state, permissions, and metadata (so you know it's usable)
- Transfer markers (tokens)
- Confirm balances & transfer events.
In this flow, we use the Direct POST path on https://api.provlabs.com/.... The same operations exist under /vault but aren't required here.
Replace these in all snippets below:
- ntesting → your own denom (marker_options.denom value you created)
- tp1…/pb1… → your addresses (testnet: tp1…, mainnet: pb1…)
Prerequisites
- Bearer token for NUVA Labs' APIs.
- Fee model ready (caller pays vs sponsor via fee-grant) with the spendable/fee-grant checks from Overview ( →)
- A caller (usually your backend) that will submit writes.
- If using restricted/permissioned flows, you'll verify that the right addresses appear in the marker's access_control (e.g., ACCESS_MINT, ACCESS_ADMIN) after creation.
Success checklist
- Marker is ACTIVE, marker_type is correct (e.g., MARKER_TYPE_COIN or MARKER_TYPE_RESTRICTED), and required_attributes (if any) are set.
- Access control lists the expected permissions (mint, admin, etc.).
- Transfer succeeds; balances and transfer events reflect the movement.
Create the Marker (Fungible Token) - Writes
Create a new marker (denom) with lifecycle settings and optional required attributes.
curl -X POST "$PROV_REST_BASE/marker" \
-H "Authorization: Bearer $PROV_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"allow_forced_transfer": false,
"allow_governance_control": true,
"marker_options": {
"denom": "ntesting",
"initial_holder_address": "tp1tledwnl9zsgcqynmjzmp8f3j25l0rj7hvx4g22",
"type": "whole_ownership"
},
"marker_type": "MARKER_TYPE_COIN",
"net_asset_value": {},
"required_attributes": []
}'
(This operation is also mirrored at POST https://api.provlabs.com/vault/marker if you standardize on the /vault base.)
Marker types: COIN vs. RESTRICTED
When creating a marker, you can specify its type using the marker_type field. The two primary types are:
- MARKER_TYPE_COIN:
- Description: A standard fungible token that can be freely transferred between accounts without additional restrictions.
- Use Case: Ideal for tokens that do not require additional governance or attribute-based restrictions, such as stablecoins, utility tokens, or fund shares.
- Behavior: Transfers are unrestricted and do not require specific attributes or permissions. Any account with sufficient balance can send or receive the token.
- MARKER_TYPE_RESTRICTED:
- Description: A permissioned fungible token that enforces additional restrictions on transfers, such as requiring specific attributes or permissions for sender and recipient accounts.
- Use Case: Suitable for tokens that require compliance with regulatory or business rules, such as RWAs (Real-World Assets) or tokens with KYC/AML requirements.
- Behavior: Transfers are restricted based on the required_attributes field. Only accounts that meet the specified attributes (e.g., pio.kyc.verified) can send or receive the token. Access control lists (ACCESS_MINT, ACCESS_ADMIN, etc.) further govern who can mint, withdraw, or manage the marker.
TL;DR: How to choose the right marker type
- Use MARKER_TYPE_COIN for general-purpose tokens where unrestricted transfers are acceptable.
- Use MARKER_TYPE_RESTRICTED when you need to enforce compliance or business rules through attributes and permissions.
Verify Marker State & Metadata - Reads
Marker Details (state, access_control, supply)
This confirms the lifecycle state (e.g., ACTIVE), permissions, and core values before you move assets.
curl -s -H "Authorization: Bearer $PROV_API_TOKEN" \
"$PROV_REST_BASE/marker/ntesting"
Alternate detail view by denom/address:
curl -s -H "Authorization: Bearer $PROV_API_TOKEN" \
"$PROV_REST_BASE/provenance/marker/v1/detail/ntesting"
Permissions (who can mint/burn/deposit/withdraw/admin)
Verifies which addresses can mint/withdraw/deposit/admin, required for permissioned flows.
curl -s -H "Authorization: Bearer $PROV_API_TOKEN" \
"$PROV_REST_BASE/provenance/marker/v1/accesscontrol/ntesting"
Holders
Shows distribution of the token across addresses (useful before/after transfers and for dashboards). Two equivalent views: the marker module's "holding" and the bank module's "denom owners".
# Marker module (holders by denom)
curl -s -H "Authorization: Bearer $PROV_API_TOKEN" \
"$PROV_REST_BASE/provenance/marker/v1/holding/ntesting"
# Bank module (denom owners)
curl -s -H "Authorization: Bearer $PROV_API_TOKEN" \
"$PROV_REST_BASE/provenance/marker/v1/denom_owners/ntesting"
Supply & metadata
Confirms total supply and denom descriptors (name/symbol/units) for UI & reporting.
# Total supply by denom
curl -s -H "Authorization: Bearer $PROV_API_TOKEN" \
"$PROV_REST_BASE/cosmos/bank/v1beta1/supply/by_denom?denom=ntesting"
# Denom metadata (name, symbol, units)
curl -s -H "Authorization: Bearer $PROV_API_TOKEN" \
"$PROV_REST_BASE/cosmos/bank/v1beta1/denoms_metadata/ntesting"
NAV history
curl -s -H "Authorization: Bearer $PROV_API_TOKEN" \
"$PROV_REST_BASE/marker/ntesting/nav"
Transfer Marker (write)
This section covers how to move token units from the caller (or specified source) to one or more recipients.
curl -X POST "$PROV_REST_BASE/marker/transfer" \
-H "Authorization: Bearer $PROV_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"operations": [
{
"amount": [{ "amount": "100", "denom": "ntesting" }],
"to_address": "tp19n4rs3lsdx4j2m57ahnurfxq7rmpmzgzer6nkc",
"type": "bank_send"
}
]
}'
Operation type: Use the exact value shown in the spec for operations[].type (currently "bank_send"). If your tenant spec enumerates additional types, use those exact strings.
Restricted markers If transfers enforce attributes or access, ensure sender/recipient satisfy requiredattributes or the caller holds the necessary ACCESS_ grants — otherwise you'll receive "missing required attribute" or "not authorized: ACCESS__". (This matches the marker module behavior.)
Post-transfer reads (confirm results)
Validate balances changed and the movement is recorded for audit/UI.
# All balances (recipient)
curl -s -H "Authorization: Bearer $PROV_API_TOKEN" \
"$PROV_REST_BASE/cosmos/bank/v1beta1/balances/tp19n4r..."
# Spendable for this denom (recipient)
curl -s -H "Authorization: Bearer $PROV_API_TOKEN" \
"$PROV_REST_BASE/cosmos/bank/v1beta1/spendable_balances/tp19n4r.../by_denom?denom=ntesting"
# Transfer events (cursor-paged; great for UI tables/audit)
curl -s -H "Authorization: Bearer $PROV_API_TOKEN" \
"$PROV_PLUS_BASE/v1/asset/transfer-events?recipient=tp19n4r...&denom=ntesting"
Transfer events (cursor-paged for UI tables)
curl -s -H "Authorization: Bearer $PROV_API_TOKEN" \
"https://api.provlabs.com/v1/asset/transfer-events?recipient={address}&denom=ntesting"
Continuation: Transfer → Trade Flow
When you're ready to list or transact the new token, continue in the Trading & Settlement hub (Markets/Orders/Commitments). See the Settlement group in API reference for Markets and Orders operations.
- Spec root: https://docs.nuvalabs.com.com/api (see Settlement → Markets/Orders)