Skip to main content

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:

  1. Create a marker
  2. Verify state, permissions, and metadata (so you know it's usable)
  3. Transfer markers (tokens)
  4. 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.

Code snippet
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.

Code snippet
curl -s -H "Authorization: Bearer $PROV_API_TOKEN" \
"$PROV_REST_BASE/marker/ntesting"

Alternate detail view by denom/address:

Code snippet
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.

Code snippet
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".

Code snippet
# Marker module (holders by denom)
curl -s -H "Authorization: Bearer $PROV_API_TOKEN" \
"$PROV_REST_BASE/provenance/marker/v1/holding/ntesting"
Code snippet
# 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.

Code snippet
# Total supply by denom
curl -s -H "Authorization: Bearer $PROV_API_TOKEN" \
"$PROV_REST_BASE/cosmos/bank/v1beta1/supply/by_denom?denom=ntesting"
Code snippet
# Denom metadata (name, symbol, units)
curl -s -H "Authorization: Bearer $PROV_API_TOKEN" \
"$PROV_REST_BASE/cosmos/bank/v1beta1/denoms_metadata/ntesting"
Code snippet
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.

Code snippet
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.

Code snippet
# All balances (recipient)
curl -s -H "Authorization: Bearer $PROV_API_TOKEN" \
"$PROV_REST_BASE/cosmos/bank/v1beta1/balances/tp19n4r..."
Code snippet
# 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"
Code snippet
# 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)

Code snippet
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.