The soulbound XP token, what mint and burn do, which balance a caller is reading, and why the chain is the one it is.
The XP token is a soulbound ERC20 that holds every customer’s XP on chain. A transfer reverts unless one side of it is the zero address, so a balance moves by mint and by burn and by nothing else.
A mint is the on-chain half of an earn, and a burn is the on-chain half of a redemption. Each XP event is one chain transaction rather than a batched one. Both are gated. Mint takes MINTER_ROLE and burn takes BURNER_ROLE, and each has an equivalent that accepts a signature from a signer the contract has registered instead of a role. The contract carries four roles, ADMIN_ROLE, MINTER_ROLE, BURNER_ROLE and SET_SIGNER_ROLE, with ADMIN_ROLE administering all four. Both carry a hash the contract consumes once, so the same operation cannot be applied twice even if it reaches the chain twice. Both emit an event carrying the customer id alongside the address and the amount, a mint as Issue and a burn as Redeem, so a chain record maps back to a customer without a lookup on your side. The transfer that is refused fails with the contract’s own KintraXPTransferDisabled error, raised whenever neither side of a movement is the zero address. That is the guarantee stated as code: no customer can send XP to another, and no integration can move it for them.
This is the part to get right before you build against it. KINTRA keeps no separate XP total of its own. A balance read sums the on-chain balances of the wallets KINTRA manages for that customer, an earn increments no stored number, and a redemption decrements none. So a caller reading GET /gateway/customers/{userId}/xp/balance is reading the chain’s number, arrived at through an indexer that follows the token’s transfer events and calls the token back for the balances they name. What you are not reading is a ledger the API maintains alongside it. The internal transaction record is the intent and the audit trail: what was granted or spent, for which customer, and which chain transaction carried it. Its amount is an unsigned magnitude and its direction is in type, so it is a history rather than a balance, and summing it is not how you find out what a customer holds.
The practical consequence is timing, and it is the same one on both pages that mention it. A balance read taken straight after an accepted earn can still answer the old number, because the credit lands when the mint is indexed rather than when the write returns. A redemption behaves the same way in reverse.
A chain transaction that reverts leaves the internal transaction at failed and the balance where it was.
XP is a whole number. The token’s decimals is fixed in code at zero rather than stored as a setting, so there is no fractional unit of a point and there never will be for this implementation. One token holds every tenant’s XP. The XP asset is one record per chain, and the separation between tenants is enforced in the API rather than by a contract per tenant. The token runs behind a proxy and is upgradeable, with the upgrade gated on ADMIN_ROLE. The address you read a balance from is the proxy’s, and it stays the same when the implementation behind it changes. Because it is an ERC20 on an EVM chain, a balance can be read from the contract directly as well as through the API, which is how the platform reads it too. Responses name chain_id and the asset address as facts about where the token lives.
KINTRA runs on LightLink, and it is the only chain the platform supports. Nothing you write names a chain. No request body carries a chain field, and the two list reads that accept chain_id take it as an optional filter, which narrows what comes back rather than choosing where anything is written. What the design asks of a chain is small writes, often, one per member event, because every earn is a mint and every redemption is a burn.
{"docsConfig":{"theme":"mint","$schema":"https://mintlify.com/docs.json","name":"KINTRA","colors":{"primary":"#35cbff","light":"#5be7ff","dark":"#0b7fa3"},"logo":{"light":"https://mintcdn.com/kintra/aV869_4X610yKJzW/logo/light.png?fit=max\u0026auto=format\u0026n=aV869_4X610yKJzW\u0026q=85\u0026s=d55bc842096a5d67e57c9ab099d58762","dark":"https://mintcdn.com/kintra/aV869_4X610yKJzW/logo/dark.png?fit=max\u0026auto=format\u0026n=aV869_4X610yKJzW\u0026q=85\u0026s=e0a69c1f9fff02d0cacd13175c0b4336"},"favicon":"https://mintcdn.com/kintra/aV869_4X610yKJzW/favicon.ico?fit=max\u0026auto=format\u0026n=aV869_4X610yKJzW\u0026q=85\u0026s=136dbc7fc4ffe42622617d330e1d8f34","api":{"playground":{"display":"interactive"},"examples":{"languages":["curl","javascript","python"],"prefill":true,"autogenerate":true}},"appearance":{"default":"dark","strict":true},"background":{"color":{"dark":"#121212"}},"fonts":{"heading":{"family":"Plus Jakarta Sans"},"body":{"family":"Plus Jakarta Sans"}},"banner":{"content":"Production environment","dismissible":false},"styling":{"latex":false},"navigation":{"pages":[]}},"deployment":{"deploymentMetadataValue":{"subdomain":"kintra","hasAudioNarration":false,"actualSubdomain":"kintra","customDomains":["docs.kintra.io"],"gitSource":{"type":"github","owner":"marco-pellar","repo":"kintra-docs","deployBranch":"main","contentDirectory":"","isPrivate":true,"mountPath":"","label":""},"chroma":{"latestBuiltDeploymentHistoryId":"6a82feba3ea465de84fb99ea","collectionId":"93576bd7-eee2-4565-b6b0-ced101e57af4","liveDeploymentHistoryId":"6a82feba3ea465de84fb99ea","schemaVersion":"v3"},"entitlements":{"AI_CHAT":{"status":"DISABLED"}},"buildId":"6a82feba3ea465de84fb99ea:success","clientVersion":"0.0.3990","searchFilterCounts":[{"language":"default","tag":"API reference","count":94},{"language":"default","tag":"Portal API","count":59},{"language":"default","tag":"Gateway API","count":34},{"language":"default","tag":"Customers","count":24},{"language":"default","tag":"Documentation","count":13},{"language":"default","tag":"Rewards","count":11},{"language":"default","tag":"Tiers","count":11},{"language":"default","tag":"Analytics","count":10},{"language":"default","tag":"Cohorts","count":7},{"language":"default","tag":"Concepts","count":6}]},"assistantConfig":{"enableAskAiButton":false,"enableStarterQuestions":false,"enableContextualStarterQuestions":false,"enableAskAiSearchBar":true},"basePath":"","hasChatPermissions":false,"hasWebMcpPermissions":false,"toggles":[{"name":"kill-isr","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"agent-mintlify-slack","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"editor-v7-file-tree","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"agent-integrations-settings","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"automations-pr-grouping","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"custom-prefix","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"analytics-v7","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"user-flows-analytics","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"no-publish-flow","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-onboarding","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"llms-txt-v2","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"pause-universal-search-reconcile","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"snapshot-serving-live","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"stripTemperatureMiddleware","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"per-site-search-delta","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"support-platform-pylon-zendesk","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"snapshot-serving","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"instant-rollback","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"granular-notifications-server","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"granular-notifications","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"editor-private-page-search","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"automations-fable","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"fixed-ai-action-pricing","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"automation-resolve-merge-conflict","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"scoped-publishing","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"mintql","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"page-level-analytics","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"editor-version-history-v2","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"editor-nav-generations","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"billing-page-v2","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workspace-projects","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"assistant-v5","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"byok-sep-25","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"fork-pr-previews","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"revalidation-jwt","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"vite-origin","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"editor-agent-model-picker","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"billing-updated-9-15","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-sso-scim","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"hobby-abuse-scan","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"dashboard-inbox","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-signup","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-enabled","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false}],"isAtlas":false,"googleFontsInlined":true},"customCss":[{"filePath":"style.css","content":":root{--kintra-code-bg:#0e0e0e;--kintra-code-surface:rgba(255, 255, 255, 0.04);--kintra-code-stroke:rgba(255, 255, 255, 0.08)}pre{background-color:var(--kintra-code-bg);border:1px solid var(--kintra-code-stroke);border-radius:12px}pre code{background-color:transparent;border:0}:not(pre)>code{background-color:var(--kintra-code-surface);border:1px solid var(--kintra-code-stroke);border-radius:6px}"}],"page":{"pagePath":"concepts/onchain-xp","slug":"/concepts/onchain-xp","pageMetadata":{"title":"On-chain XP","description":"The soulbound XP token, what mint and burn do, which balance a caller is reading, and why the chain is the one it is.","href":"/concepts/onchain-xp"},"description":{"compiledSource":"\"use strict\";\nconst {jsx: _jsx} = arguments[0];\nconst {useMDXComponents: _provideComponents} = arguments[0];\nfunction _createMdxContent(props) {\n const _components = {\n p: \"p\",\n ..._provideComponents(),\n ...props.components\n };\n return _jsx(_components.p, {\n children: \"The soulbound XP token, what mint and burn do, which balance a caller is reading, and why the chain is the one it is.\"\n });\n}\nfunction MDXContent(props = {}) {\n const {wrapper: MDXLayout} = {\n ..._provideComponents(),\n ...props.components\n };\n return MDXLayout ? _jsx(MDXLayout, {\n ...props,\n children: _jsx(_createMdxContent, {\n ...props\n })\n }) : _createMdxContent(props);\n}\nreturn {\n default: MDXContent\n};\n","frontmatter":{},"scope":{}},"pageType":"default","mdx":{"mdxSource":{"compiledSource":"\"use strict\";const{Fragment:_Fragment,jsx:_jsx,jsxs:_jsxs}=arguments[0];const{useMDXComponents:_provideComponents}=arguments[0];function _createMdxContent(props){const _components={a:`a`,code:`code`,li:`li`,p:`p`,ul:`ul`,..._provideComponents(),...props.components},{Heading,Warning}=_components;if(!Heading)_missingMdxReference(`Heading`,true);if(!Warning)_missingMdxReference(`Warning`,true);return _jsxs(_Fragment,{children:[_jsx(_components.p,{children:`The XP token is a soulbound ERC20 that holds every customer’s XP on chain. A transfer reverts unless one side of it is the zero address, so a balance moves by mint and by burn and by nothing else. `}),`\n`,_jsx(Heading,{level:`2`,id:`mint-and-burn-are-the-two-halves-you-already-know`,children:`Mint and burn are the two halves you already know`}),`\n`,_jsx(_components.p,{children:`A mint is the on-chain half of an earn, and a burn is the on-chain half of a redemption. Each XP event is one chain transaction rather than a batched one. `}),`\n`,_jsxs(_components.p,{children:[`Both are gated. Mint takes `,_jsx(_components.code,{children:`MINTER_ROLE`}),` and burn takes `,_jsx(_components.code,{children:`BURNER_ROLE`}),`, and each has an equivalent that accepts a signature from a signer the contract has registered instead of a role. The contract carries four roles, `,_jsx(_components.code,{children:`ADMIN_ROLE`}),`, `,_jsx(_components.code,{children:`MINTER_ROLE`}),`, `,_jsx(_components.code,{children:`BURNER_ROLE`}),` and `,_jsx(_components.code,{children:`SET_SIGNER_ROLE`}),`, with `,_jsx(_components.code,{children:`ADMIN_ROLE`}),` administering all four. `]}),`\n`,_jsx(_components.p,{children:`Both carry a hash the contract consumes once, so the same operation cannot be applied twice even if it reaches the chain twice. `}),`\n`,_jsxs(_components.p,{children:[`Both emit an event carrying the customer id alongside the address and the amount, a mint as `,_jsx(_components.code,{children:`Issue`}),` and a burn as `,_jsx(_components.code,{children:`Redeem`}),`, so a chain record maps back to a customer without a lookup on your side. `]}),`\n`,_jsxs(_components.p,{children:[`The transfer that is refused fails with the contract’s own `,_jsx(_components.code,{children:`KintraXPTransferDisabled`}),` error, raised whenever neither side of a movement is the zero address. That is the guarantee stated as code: no customer can send XP to another, and no integration can move it for them. `]}),`\n`,_jsx(Heading,{level:`2`,id:`there-is-one-balance-and-the-chain-holds-it`,children:`There is one balance, and the chain holds it`}),`\n`,_jsx(_components.p,{children:`This is the part to get right before you build against it. KINTRA keeps no separate XP total of its own. A balance read sums the on-chain balances of the wallets KINTRA manages for that customer, an earn increments no stored number, and a redemption decrements none. `}),`\n`,_jsxs(_components.p,{children:[`So a caller reading `,_jsx(_components.code,{children:`GET /gateway/customers/{userId}/xp/balance`}),` is reading the chain’s number, arrived at through an indexer that follows the token’s transfer events and calls the token back for the balances they name. `]}),`\n`,_jsxs(_components.p,{children:[`What you are not reading is a ledger the API maintains alongside it. The internal transaction record is the intent and the audit trail: what was granted or spent, for which customer, and which chain transaction carried it. Its `,_jsx(_components.code,{children:`amount`}),` is an unsigned magnitude and its direction is in `,_jsx(_components.code,{children:`type`}),`, so it is a history rather than a balance, and summing it is not how you find out what a customer holds. `]}),`\n`,_jsx(Warning,{children:_jsx(_components.p,{children:`The practical consequence is timing, and it is the same one on both pages that mention it. A balance read taken straight after an accepted earn can still answer the old number, because the credit lands when the mint is indexed rather than when the write returns. A redemption behaves the same way in reverse. `})}),`\n`,_jsxs(_components.p,{children:[`A chain transaction that reverts leaves the internal transaction at `,_jsx(_components.code,{children:`failed`}),` and the balance where it was. `]}),`\n`,_jsx(Heading,{level:`2`,id:`what-the-token-is-and-is-not`,children:`What the token is and is not`}),`\n`,_jsxs(_components.p,{children:[`XP is a whole number. The token’s `,_jsx(_components.code,{children:`decimals`}),` is fixed in code at zero rather than stored as a setting, so there is no fractional unit of a point and there never will be for this implementation. `]}),`\n`,_jsx(_components.p,{children:`One token holds every tenant’s XP. The XP asset is one record per chain, and the separation between tenants is enforced in the API rather than by a contract per tenant. `}),`\n`,_jsxs(_components.p,{children:[`The token runs behind a proxy and is upgradeable, with the upgrade gated on `,_jsx(_components.code,{children:`ADMIN_ROLE`}),`. The address you read a balance from is the proxy’s, and it stays the same when the implementation behind it changes. `]}),`\n`,_jsxs(_components.p,{children:[`Because it is an ERC20 on an EVM chain, a balance can be read from the contract directly as well as through the API, which is how the platform reads it too. Responses name `,_jsx(_components.code,{children:`chain_id`}),` and the asset address as facts about where the token lives. `]}),`\n`,_jsx(Heading,{level:`2`,id:`the-chain`,children:`The chain`}),`\n`,_jsx(_components.p,{children:`KINTRA runs on LightLink, and it is the only chain the platform supports. `}),`\n`,_jsxs(_components.p,{children:[`Nothing you write names a chain. No request body carries a chain field, and the two list reads that accept `,_jsx(_components.code,{children:`chain_id`}),` take it as an optional filter, which narrows what comes back rather than choosing where anything is written. `]}),`\n`,_jsx(_components.p,{children:`What the design asks of a chain is small writes, often, one per member event, because every earn is a mint and every redemption is a burn. `}),`\n`,_jsx(Heading,{level:`2`,id:`where-to-go-next`,children:`Where to go next`}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsxs(_components.li,{children:[_jsx(_components.a,{href:`/concepts/xp-and-the-ledger`,children:`XP and the ledger`}),` for what an earn and a redemption look like from the API side.`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.a,{href:`/concepts/rewards-and-redemptions`,children:`Rewards and redemptions`}),` for the record a burn is written against.`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.a,{href:`/architecture`,children:`Architecture`}),` for tenant isolation and the settlement path in one place.`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.a,{href:`/concepts/tiers`,children:`Tiers`}),` for what the balance is compared against.`]}),`\n`]})]})}function MDXContent(props={}){const{wrapper:MDXLayout}={..._provideComponents(),...props.components};return MDXLayout?_jsx(MDXLayout,{...props,children:_jsx(_createMdxContent,{...props})}):_createMdxContent(props)}return{default:MDXContent};function _missingMdxReference(id,component){throw new Error(`Expected `+(component?`component`:`object`)+\" `\"+id+\"` to be defined: you likely forgot to import, pass, or provide it.\")}","frontmatter":{},"scope":{"config":{},"pageMetadata":{"title":"On-chain XP","description":"The soulbound XP token, what mint and burn do, which balance a caller is reading, and why the chain is the one it is.","href":"/concepts/onchain-xp"}}},"mdxSourceWithNoJs":null},"mdxExtracts":{"tableOfContents":[{"title":"Mint and burn are the two halves you already know","slug":"mint-and-burn-are-the-two-halves-you-already-know","depth":2,"children":[]},{"title":"There is one balance, and the chain holds it","slug":"there-is-one-balance-and-the-chain-holds-it","depth":2,"children":[]},{"title":"What the token is and is not","slug":"what-the-token-is-and-is-not","depth":2,"children":[]},{"title":"The chain","slug":"the-chain","depth":2,"children":[]},{"title":"Where to go next","slug":"where-to-go-next","depth":2,"children":[]}],"codeExamples":{}},"jsLinks":[],"subdomain":"kintra","siteName":"KINTRA","title":"On-chain XP - KINTRA","navMaps":{"firstHrefInVersion":{},"firstHrefInLanguage":{}},"lastModified":"2026-08-17T12:30:09.656Z","originalFileLocation":"concepts/onchain-xp.mdx"},"headHtml":"\u003cscript data-mint-head>(function(){var d=document.documentElement,p=\"dark\";if(!p){try{p=localStorage.getItem(\"isDarkMode\")}catch(e){}if(p==='true')p='dark';else if(p==='false')p='light';if(p!=='light'\u0026\u0026p!=='dark'\u0026\u0026p!=='system')p=\"dark\"}var r=p==='system'?(matchMedia(\"(prefers-color-scheme: dark)\").matches?'dark':'light'):p;d.classList.remove(r==='dark'?'light':'dark');d.classList.add(r);d.setAttribute(\"data-theme-preference\",p)})();\u003c/script>\u003cmeta data-mint-head name=\"description\" content=\"The soulbound XP token, what mint and burn do, which balance a caller is reading, and why the chain is the one it is.\">\u003cmeta data-mint-head name=\"application-name\" content=\"KINTRA\">\u003cmeta data-mint-head name=\"generator\" content=\"Mintlify\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"192x192\" href=\"/mintlify-assets/_mintlify/favicons/kintra/ZtFEHcUbLmdYiJ-1/_generated/favicon/android-chrome-192x192.png\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"apple-touch-icon\" type=\"image/png\" sizes=\"180x180\" href=\"/mintlify-assets/_mintlify/favicons/kintra/ZtFEHcUbLmdYiJ-1/_generated/favicon/apple-touch-icon.png\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"16x16\" href=\"/mintlify-assets/_mintlify/favicons/kintra/ZtFEHcUbLmdYiJ-1/_generated/favicon/favicon-16x16.png\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"32x32\" href=\"/mintlify-assets/_mintlify/favicons/kintra/ZtFEHcUbLmdYiJ-1/_generated/favicon/favicon-32x32.png\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"shortcut icon\" type=\"image/x-icon\" href=\"/mintlify-assets/_mintlify/favicons/kintra/ZtFEHcUbLmdYiJ-1/_generated/favicon/favicon.ico\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"192x192\" href=\"/mintlify-assets/_mintlify/favicons/kintra/ZtFEHcUbLmdYiJ-1/_generated/favicon-dark/android-chrome-192x192.png\" media=\"(prefers-color-scheme: dark)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"16x16\" href=\"/mintlify-assets/_mintlify/favicons/kintra/ZtFEHcUbLmdYiJ-1/_generated/favicon-dark/favicon-16x16.png\" media=\"(prefers-color-scheme: dark)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"32x32\" href=\"/mintlify-assets/_mintlify/favicons/kintra/ZtFEHcUbLmdYiJ-1/_generated/favicon-dark/favicon-32x32.png\" media=\"(prefers-color-scheme: dark)\">\u003clink data-mint-head rel=\"shortcut icon\" type=\"image/x-icon\" href=\"/mintlify-assets/_mintlify/favicons/kintra/ZtFEHcUbLmdYiJ-1/_generated/favicon-dark/favicon.ico\" media=\"(prefers-color-scheme: dark)\">\u003cmeta data-mint-head property=\"og:title\" content=\"On-chain XP - KINTRA\">\u003cmeta data-mint-head property=\"og:description\" content=\"The soulbound XP token, what mint and burn do, which balance a caller is reading, and why the chain is the one it is.\">\u003cmeta data-mint-head property=\"og:site_name\" content=\"KINTRA\">\u003cmeta data-mint-head property=\"og:url\" content=\"https://docs.kintra.io/concepts/onchain-xp\">\u003cmeta data-mint-head property=\"og:type\" content=\"website\">\u003cmeta data-mint-head property=\"og:image\" content=\"https://kintra.mintlify.app/_mintlify/api/og/v2?division=Concepts\u0026amp;title=On-chain+XP\u0026amp;description=The+soulbound+XP+token%2C+what+mint+and+burn+do%2C+which+balance+a+caller+is+reading%2C+and+why+the+chain+is+the+one+it+is.\u0026amp;theme=7168baa81e08787f570d323b\u0026amp;signature=b00b212a0eded59273cc8c0ff534f06c7cbcdb02a7a2f4cd807b02fdc7da4d14\">\u003cmeta data-mint-head property=\"og:image:width\" content=\"1200\">\u003cmeta data-mint-head property=\"og:image:height\" content=\"630\">\u003cmeta data-mint-head name=\"twitter:card\" content=\"summary_large_image\">\u003cmeta data-mint-head name=\"twitter:title\" content=\"On-chain XP - KINTRA\">\u003cmeta data-mint-head name=\"twitter:description\" content=\"The soulbound XP token, what mint and burn do, which balance a caller is reading, and why the chain is the one it is.\">\u003cmeta data-mint-head name=\"twitter:image\" content=\"https://kintra.mintlify.app/_mintlify/api/og/v2?division=Concepts\u0026amp;title=On-chain+XP\u0026amp;description=The+soulbound+XP+token%2C+what+mint+and+burn+do%2C+which+balance+a+caller+is+reading%2C+and+why+the+chain+is+the+one+it+is.\u0026amp;theme=7168baa81e08787f570d323b\u0026amp;signature=b00b212a0eded59273cc8c0ff534f06c7cbcdb02a7a2f4cd807b02fdc7da4d14\">\u003cmeta data-mint-head name=\"twitter:image:width\" content=\"1200\">\u003cmeta data-mint-head name=\"twitter:image:height\" content=\"630\">\u003cmeta data-mint-head name=\"msapplication-config\" content=\"/mintlify-assets/_mintlify/favicons/kintra/ZtFEHcUbLmdYiJ-1/_generated/favicon/browserconfig.xml\">\u003cmeta data-mint-head name=\"apple-mobile-web-app-title\" content=\"KINTRA\">\u003cmeta data-mint-head name=\"msapplication-TileColor\" content=\"#35cbff\">\u003clink data-mint-head rel=\"canonical\" href=\"https://docs.kintra.io/concepts/onchain-xp\">\u003clink data-mint-head rel=\"alternate\" type=\"application/xml\" href=\"/sitemap.xml\">\u003clink data-mint-head rel=\"alternate\" type=\"text/markdown\" href=\"/concepts/onchain-xp.md\">\u003cscript data-mint-head type=\"application/ld+json\">{\"@context\":\"https://schema.org\",\"@graph\":[{\"@type\":\"Organization\",\"@id\":\"https://docs.kintra.io/#organization\",\"name\":\"KINTRA\",\"url\":\"https://docs.kintra.io\",\"logo\":{\"@type\":\"ImageObject\",\"url\":\"https://mintcdn.com/kintra/aV869_4X610yKJzW/logo/light.png?fit=max\u0026auto=format\u0026n=aV869_4X610yKJzW\u0026q=85\u0026s=d55bc842096a5d67e57c9ab099d58762\"}},{\"@type\":\"WebSite\",\"@id\":\"https://docs.kintra.io#website\",\"name\":\"KINTRA\",\"url\":\"https://docs.kintra.io\",\"publisher\":{\"@id\":\"https://docs.kintra.io/#organization\"}},{\"@type\":\"WebPage\",\"@id\":\"https://docs.kintra.io/concepts/onchain-xp#webpage\",\"url\":\"https://docs.kintra.io/concepts/onchain-xp\",\"name\":\"On-chain XP\",\"description\":\"The soulbound XP token, what mint and burn do, which balance a caller is reading, and why the chain is the one it is.\",\"dateModified\":\"2026-08-17T12:30:09.656Z\",\"isPartOf\":{\"@id\":\"https://docs.kintra.io#website\"},\"breadcrumb\":{\"@id\":\"https://docs.kintra.io/concepts/onchain-xp#breadcrumb\"}},{\"@type\":\"BreadcrumbList\",\"@id\":\"https://docs.kintra.io/concepts/onchain-xp#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Concepts\",\"item\":\"https://docs.kintra.io/concepts/tenants\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"On-chain XP\",\"item\":\"https://docs.kintra.io/concepts/onchain-xp\"}]},{\"@type\":[\"Article\",\"TechArticle\"],\"@id\":\"https://docs.kintra.io/concepts/onchain-xp#article\",\"headline\":\"On-chain XP\",\"name\":\"On-chain XP\",\"description\":\"The soulbound XP token, what mint and burn do, which balance a caller is reading, and why the chain is the one it is.\",\"url\":\"https://docs.kintra.io/concepts/onchain-xp\",\"mainEntityOfPage\":{\"@id\":\"https://docs.kintra.io/concepts/onchain-xp#webpage\"},\"dateModified\":\"2026-08-17T12:30:09.656Z\",\"publisher\":{\"@id\":\"https://docs.kintra.io/#organization\"},\"isPartOf\":{\"@id\":\"https://docs.kintra.io#website\"}}]}\u003c/script>\u003cscript data-mint-head type=\"application/ld+json\">{\"@context\":\"https://schema.org\",\"@type\":\"WebSite\",\"name\":\"KINTRA\",\"creator\":{\"@type\":\"Organization\",\"name\":\"Mintlify\",\"url\":\"https://mintlify.com\"}}\u003c/script>","siteName":"KINTRA","nav":{"global":null,"tabs":[{"tab":"Documentation","groups":[{"group":"Get started","pages":[{"title":"KINTRA","href":""},{"title":"Quickstart","href":"/quickstart"},{"title":"Authentication","href":"/authentication"},{"title":"Request conventions","href":"/conventions"},{"title":"Architecture","href":"/architecture"}]},{"group":"Concepts","pages":[{"title":"Tenants","href":"/concepts/tenants"},{"title":"Customers","href":"/concepts/customers"},{"title":"XP and the ledger","href":"/concepts/xp-and-the-ledger"},{"title":"Tiers","href":"/concepts/tiers"},{"title":"Rewards and redemptions","description":"The lifecycle from a reward you publish to a redemption that has settled, with the refusals along the way and what each record means.","href":"/concepts/rewards-and-redemptions"},{"title":"On-chain XP","href":"/concepts/onchain-xp"}]},{"group":"Walkthroughs","pages":[{"title":"Onboard a customer","description":"A single request that registers a customer with everything you know about them: identity details, attributes and cohort.","href":"/walkthroughs/onboard-a-customer"},{"title":"Award and redeem XP","href":"/walkthroughs/award-and-redeem-xp"}]}]},{"tab":"API reference","pages":[{"title":"API reference","href":"/api-reference/overview"}]}]},"title":"On-chain XP - KINTRA","buildId":"dpl_2oYXwqkEXirXBPk8wV1FtM5USFWi","deploymentId":"dpl_2oYXwqkEXirXBPk8wV1FtM5USFWi","dynamics":[],"chunks":[]}