Relic Payment Authorizations
Use configurable relic currencies for instant customer payment, account credit, B2B settlement, and authorize/capture/reversal order flows.
Local portal docs
Relic Payment Authorizations let a website hold a user's relic currency for an order, then either capture it when the order completes or reverse it when the order is cancelled.
What Relics Is
Relics is a configurable currency system for The Crimson Market ecosystem. Approved businesses can create their own currency branches with their own name, icon, pricing ratio, payout currency, exchange targets, purchase setting, withdrawal setting, and operating rules.
A relic currency can be configured for different business models:
- Buy and sell: customers can purchase the currency and later sell, withdraw, or exchange it where the issuer enables that rail.
- Buy only: customers can purchase and spend the currency, while sell-side or withdrawal movement stays disabled.
- Sell or withdrawal only: the business can support exits, redemptions, or treasury settlement without offering direct customer purchase.
- Closed-loop internal value: the business can use the currency for rewards, account credit, customer payments, B2B settlement, automated pricing offsets, or partner-network settlement.
Relic balances settle on a fast internal ledger. A currency can stay fully off-chain, or the issuing business can map it to an on-chain asset strategy while still using the relic ledger for instant account balance, authorization, capture, reversal, and escrow workflows.
Common use cases:
- customers pay instantly with held relic value
- websites apply automated pricing offsets or account-credit settlement
- businesses settle partner, reseller, and B2B sales
- relic-funded order portions avoid external payment processor fees once the value is already held in the ledger
- marketplace and service transactions use escrow instead of informal chat-based trust
The escrow model is four-way: customer, counterparty or merchant, currency issuer or treasury, and vault/admin dispute layer. Each escrow keeps the amount, participants, order context, expiry, completion, cancellation, and dispute history attached to one auditable record.
Relic payment movement uses three settlement states:
- Authorize: place a temporary hold on a user's available relic balance.
- Capture: settle the authorization, debit the user's relic balance, and credit the app client's merchant treasury.
- Reverse: release the authorization without debiting the user.
Use this flow when relic currency is part of checkout, account credit, stored value, rewards redemption, or another order settlement process.
Summary
- Create an OAuth application in the Developers portal.
- Store the
clientIdandclientSecreton your server. - Ask TCM to enable relic payment authorizations for your client, the currencies you need, your merchant treasury Transfer ID, and one merchant withdrawal currency.
- Sign users in with TCM OAuth so your service can identify the TCM account id.
- Authorize relic currency during checkout.
- Capture the authorization when the order is settled, or reverse it when the order fails or is cancelled.
- Use the Merchant tab in the Relics vault to review captured purchases and request settlement.
Never expose your clientSecret in browser code. All authorization, capture, and reversal calls are server-to-server.
Merchant Settlement Setup
TCM configures two merchant settlement fields for each relic-enabled app client:
treasuryUserId: the merchant receiving account. Captured relics are credited here.merchantWithdrawalCurrency: the single payout currency used for merchant settlement requests, such asAUD,JPY, orUSD.
Each capture creates a settlement lot. The lot stores the relic amount, the branch-stable base amount, the configured withdrawal currency, the exchange rate, and the locked withdrawal amount at capture time.
For example, if Charades Coin is configured as 100 charades-coin = 1 AUD and the merchant withdrawal currency is JPY, then a capture of 10,000 Charades Coin records:
10,000Charades Coin credited to the merchant treasury.100 AUDbase value.- the live
AUD -> JPYrate at capture. - the resulting JPY payout value locked for that captured purchase.
Partial settlement requests consume unsettled lots first-in, first-out. That keeps the relic deduction aligned with the exact relics captured on the merchant website while preserving the payout value that was locked when each purchase was captured.
OAuth Setup
Create an application at:
https://www.thecrimsonmarket.com/developers/apps/createRecommended OAuth environment values:
NEXT_PUBLIC_TCM_CLIENT_ID="paste-your-client-id"
TCM_OAUTH_CLIENT_SECRET="paste-your-client-secret"
TCM_OAUTH_API_URL="https://www.thecrimsonmarket.com/mana"
NEXT_PUBLIC_TCM_OAUTH_WEB_URL="https://www.thecrimsonmarket.com"Register your callback URL exactly as it exists in production, for example:
https://merchant.example.com/auth/tcm/callbackFor a Next.js app, use the SDK server-backed flow:
@crimsoncorp/oauth-reactThe user id returned from TCM OAuth is the accountId you send to the relic payment authorization API.
List Available Currencies
Fetch the enabled relic currencies before showing payment, account-credit, settlement, or treasury options:
GET https://www.thecrimsonmarket.com/relics/api/relics/currenciesResponse:
{
"success": true,
"data": {
"currencies": [
{
"key": "forumgold-v2",
"name": "Forum Gold v2",
"description": "Default Forum Gold v2 balance.",
"iconUrl": "/images/ForumGoldIcon.webp",
"iconObjectKey": "",
"infoUrl": "https://www.thecrimsonmarket.com/forumgold",
"parentKey": null,
"enabled": true,
"capabilities": {
"buy": false,
"sell": false,
"withdraw": false,
"wager": true,
"exchange": false
},
"settlement": {
"payoutRatioRelics": 100,
"payoutCurrency": "EUR",
"walletTargetCurrency": "USD",
"exchangeTargets": []
},
"isSystem": true
}
]
}
}Use key as the relicType value in payment authorization, transfer, widget, and balance requests. Capability flags describe what the currency supports globally; your OAuth client must still be enabled for a currency before it can authorize, capture, reverse, or transfer that currency.
Endpoints
Base URL:
https://www.thecrimsonmarket.com/relicsAuthorize
POST /api/relics/payment-authorizations
Content-Type: application/jsonRequest:
{
"clientId": "tcm_xxx",
"clientSecret": "server-side-client-secret",
"accountId": "64c672ff9e49204d7f5dd5ca",
"amount": 750,
"relicType": "forum-gold",
"merchantReference": "order_100045_relic_auth",
"orderId": "order_100045",
"statementDescriptor": "Order 100045 relic payment",
"notes": "Relic payment authorization for order 100045",
"expiresAt": "2026-07-12T13:00:00.000Z"
}Required fields:
clientIdclientSecretaccountIdamountrelicTypemerchantReference
Optional fields:
orderIdstatementDescriptornotesexpiresAt
Response:
{
"success": true,
"data": {
"authorizationId": "pay_auth_example",
"status": "active",
"clientId": "tcm_xxx",
"accountId": "64c672ff9e49204d7f5dd5ca",
"relicType": "forum-gold",
"currency": {
"key": "forum-gold",
"name": "Forum Gold"
},
"amount": 750,
"expiresAt": "2026-07-12T13:00:00.000Z",
"createdAt": "2026-07-12T12:30:00.000Z",
"alreadyProcessed": false,
"merchantReference": "order_100045_relic_auth",
"orderId": "order_100045"
}
}Capture
POST /api/relics/payment-authorizations/{authorizationId}/capture
Content-Type: application/jsonRequest:
{
"clientId": "tcm_xxx",
"clientSecret": "server-side-client-secret",
"settlementReference": "order_100045_paid",
"notes": "Order 100045 settled"
}Response:
{
"success": true,
"data": {
"authorizationId": "pay_auth_example",
"status": "confirmed",
"clientId": "tcm_xxx",
"accountId": "64c672ff9e49204d7f5dd5ca",
"relicType": "forum-gold",
"amount": 750,
"settlementReference": "order_100045_paid",
"settlementUserId": "merchant_treasury_transfer_id",
"settlement": {
"baseCurrency": "AUD",
"baseAmount": 7.5,
"withdrawalCurrency": "JPY",
"withdrawalAmount": 735.42,
"exchangeRate": 98.056
},
"accountBalance": 4250,
"treasuryBalance": 15750,
"amountCaptured": 750
}
}The settlement object is a capture-time snapshot. Do not recalculate it later for accounting. Merchant settlement requests use these locked lots.
Reverse
POST /api/relics/payment-authorizations/{authorizationId}/reversal
Content-Type: application/jsonRequest:
{
"clientId": "tcm_xxx",
"clientSecret": "server-side-client-secret",
"reversalReference": "order_100045_cancelled",
"notes": "Order 100045 cancelled before settlement"
}Response:
{
"success": true,
"data": {
"authorizationId": "pay_auth_example",
"status": "released",
"clientId": "tcm_xxx",
"accountId": "64c672ff9e49204d7f5dd5ca",
"relicType": "forum-gold",
"amount": 750,
"reversalReference": "order_100045_cancelled",
"amountReleased": 750
}
}Operational Rules
merchantReferenceis idempotent per OAuth client.- Repeating the same authorization request returns the existing authorization.
- A client can only authorize currencies enabled for that client.
- A client can only capture or reverse authorizations it created.
- Captured authorizations cannot be reversed through this API.
- Reversed, expired, or already captured authorizations cannot be captured again.
- Captures require a configured merchant treasury account.
- Merchant payout currency is configured by TCM and locked per capture.
- Keep
clientSecreton the server only.
Merchant Operations
Merchants with a configured treasury account see a Merchant tab in the Relics vault.
The Merchant tab shows:
- treasury balances in relic units
- unsettled captured purchases
- base value, such as AUD for AUD-backed Charades Coin
- locked withdrawal value in the configured merchant payout currency
- previous settlement requests
Merchants can request partial settlement by entering a relic amount. Relics consumes the oldest unsettled capture lots first. After the request is created, an admin manually pays the locked withdrawal amount through the agreed external method, then marks the request settled in the Relics admin dashboard. At that point the exact requested relic amount is deducted from the merchant treasury.
Coding Agent Prompt
After creating an app, copy the prompt below into your coding agent and replace the placeholders.
You are integrating TCM OAuth and Relic Payment Authorizations into my website.
Use these credentials and URLs:
- TCM OAuth client id: <CLIENT_ID>
- TCM OAuth client secret: <CLIENT_SECRET>
- TCM OAuth API URL: https://www.thecrimsonmarket.com/mana
- TCM OAuth web URL: https://www.thecrimsonmarket.com
- Relic API base URL: https://www.thecrimsonmarket.com/relics
- OAuth callback URL in my app: <CALLBACK_URL>
- Relic currency key: <RELIC_TYPE>
OAuth endpoints and expected identity data:
- Authorization URL: https://www.thecrimsonmarket.com/oauth/authorize
- Token URL: https://www.thecrimsonmarket.com/mana/oauth/token
- Userinfo URL: https://www.thecrimsonmarket.com/mana/oauth/userinfo
- Currency discovery URL: https://www.thecrimsonmarket.com/relics/api/relics/currencies
- Callback route: <CALLBACK_URL>
- Required server env:
NEXT_PUBLIC_TCM_CLIENT_ID="<CLIENT_ID>"
TCM_OAUTH_CLIENT_SECRET="<CLIENT_SECRET>"
TCM_OAUTH_API_URL="https://www.thecrimsonmarket.com/mana"
NEXT_PUBLIC_TCM_OAUTH_WEB_URL="https://www.thecrimsonmarket.com"
- User identity shape to persist:
{
"accountId": "<TCM user id from userInfo._id or userInfo.userId>",
"email": "<userInfo.email when granted>",
"displayName": "<userInfo.userName or userInfo.name when available>"
}
Requirements:
1. Keep the OAuth client secret server-side only.
2. Add TCM OAuth login using @crimsoncorp/oauth-react.
3. Register/use the callback route <CALLBACK_URL>.
4. Store the signed-in TCM user id from OAuth as accountId.
5. Fetch GET https://www.thecrimsonmarket.com/relics/api/relics/currencies to list available currencies. Use data.currencies[].key as relicType and show capability flags from data.currencies[].capabilities.
6. During checkout, call POST https://www.thecrimsonmarket.com/relics/api/relics/payment-authorizations from my server.
7. Use this authorization request shape:
{
"clientId": "<CLIENT_ID>",
"clientSecret": process.env.TCM_OAUTH_CLIENT_SECRET,
"accountId": "<TCM_USER_ID>",
"amount": 750,
"relicType": "<RELIC_TYPE>",
"merchantReference": "<UNIQUE_ORDER_AUTH_REFERENCE>",
"orderId": "<ORDER_ID>",
"statementDescriptor": "<ORDER_DESCRIPTION>",
"notes": "<ORDER_NOTES>",
"expiresAt": "<OPTIONAL_ISO_DATE>"
}
8. Persist data.authorizationId on the order.
9. When the order is paid or fulfilled, call POST https://www.thecrimsonmarket.com/relics/api/relics/payment-authorizations/{authorizationId}/capture with:
{
"clientId": "<CLIENT_ID>",
"clientSecret": process.env.TCM_OAUTH_CLIENT_SECRET,
"settlementReference": "<UNIQUE_SETTLEMENT_REFERENCE>",
"notes": "<SETTLEMENT_NOTES>"
}
10. When the order is cancelled, payment fails, or the user abandons checkout after authorization, call POST https://www.thecrimsonmarket.com/relics/api/relics/payment-authorizations/{authorizationId}/reversal with:
{
"clientId": "<CLIENT_ID>",
"clientSecret": process.env.TCM_OAUTH_CLIENT_SECRET,
"reversalReference": "<UNIQUE_REVERSAL_REFERENCE>",
"notes": "<REVERSAL_NOTES>"
}
11. Treat merchantReference as idempotent per OAuth client.
12. Read and store capture response settlement fields for merchant reporting:
{
"settlement": {
"baseCurrency": "<BASE_CURRENCY>",
"baseAmount": 7.5,
"withdrawalCurrency": "<MERCHANT_WITHDRAWAL_CURRENCY>",
"withdrawalAmount": 735.42,
"exchangeRate": 98.056
},
"settlementUserId": "<MERCHANT_TREASURY_TRANSFER_ID>"
}
13. Do not recalculate merchant payout values later. Relics locks payout value at capture time and handles partial settlement requests from the merchant vault.
14. Never call secret-bearing relic API routes directly from browser code because they require the client secret. The currency discovery endpoint is public and can be called from the browser or server.
Implement this using the existing framework patterns in my app, including server routes/actions for all secret-bearing calls.