Skip to content

Assets API

Token operations on any configured chain. These endpoints work for any registered asset — replace :symbol with USDT, USDC, IMC, or any custom token — on any registered chain, EVM or Stellar, via ?chain=.

API ConfigurationNot configured

List Assets

List All Assets
curl -X GET "http://localhost:8100/api/v1/assets" \
  -H "Content-Type: application/json" \
  -H "X-Service-Token: YOUR_TOKEN_HERE"
Response200
{ "assets": [{ "Symbol": "USDT", "Contract": "0x3C8E...DDDF", "Decimals": 6, "chain": "celo" }, { "Symbol": "IMC", "Contract": "0xF150...d5A2", "Decimals": 6, "chain": "celo" }], "count": 2 }

List Chains

List Chains
curl -X GET "http://localhost:8100/api/v1/chains" \
  -H "Content-Type: application/json" \
  -H "X-Service-Token: YOUR_TOKEN_HERE"
Response200
{ "chains": [{ "name": "celo", "chainId": 11142220, "assets": [...] }, { "name": "stellar", "assets": [...] }], "count": 2 }

stellar only appears once STELLAR_RELAYER_SEED is configured — see Setting Up Stellar →. Absent that, this instance only ever returns celo (and whatever other EVM chains are configured).


Token Balance

IMC Balance (Celo)
curl -X GET "http://localhost:8100/api/v1/assets/imc/balance?externalUserId=123&tenantSlug=comet" \
  -H "Content-Type: application/json" \
  -H "X-Service-Token: YOUR_TOKEN_HERE"
Response200
{ "symbol": "IMC", "chain": "celo", "balance": "447000000", "decimals": 6, "humanAmount": 447 }
Native Balance (Stellar)
curl -X GET "http://localhost:8100/api/v1/assets/xlm/balance?externalUserId=123&chain=stellar" \
  -H "Content-Type: application/json" \
  -H "X-Service-Token: YOUR_TOKEN_HERE"
Response200
{ "symbol": "XLM", "chain": "stellar", "balance": "30000000", "decimals": 7, "humanAmount": 3 }

Query Parameters:

ParamTypeRequiredDescription
externalUserIdstringYesWallet owner (your own user ID)
tenantSlugstringNoTenant (defaults to "comet")
chainstringNoChain (defaults to "celo") — pass stellar for a Stellar-family balance

Stellar decimals are fixed at 7

Native XLM balances are always 7 decimals — that's a Stellar protocol constant, not a per-asset setting like EVM's decimals config. Registered Stellar assets (non-native) use whatever decimals they were registered with, same as EVM.


Mint Tokens

Mints tokens directly to a user's custodial wallet using the relayer key.

Mint IMC (Celo)
curl -X POST "http://localhost:8100/api/v1/assets/imc/mint" \
  -H "Content-Type: application/json" \
  -H "X-Service-Token: YOUR_TOKEN_HERE" \
  -d '{"externalUserId": "123", "amountBase": 10000000, "externalId": "mint-001"}'
Response200
{ "amount": 10, "chain": "celo", "symbol": "IMC", "txHash": "0x..." }

Request Fields:

FieldTypeRequiredDescription
externalUserIdstringYesTarget user
amountBasenumberYesAmount in base units (6 decimals: 1000000 = 1.0 token)
externalIdstringYesIdempotency key

Backing-aware accounting

Mints are journaled with type-aware backing. Airtime-backed assets (type: airtime) debit the airtime inventory account; all other assets debit the tenant treasury.

Works the same way with ?chain=stellar for a registered Stellar asset — minting there issues the asset (the relayer account must be the asset's issuer, per Stellar's protocol) rather than calling a token contract.


Send Tokens

Transfers tokens from a user's wallet to a recipient.

Send IMC
curl -X POST "http://localhost:8100/api/v1/assets/imc/send" \
  -H "Content-Type: application/json" \
  -H "X-Service-Token: YOUR_TOKEN_HERE" \
  -d '{"externalUserId": "123", "to": "0xRecipientAddress", "amountBase": "5000000"}'
Response200
{ "txHash": "0x...", "chain": "celo", "symbol": "IMC", "amount": 5 }

Request Fields:

FieldTypeRequiredDescription
externalUserIdstringYesSender
tostringYesRecipient address — an EVM 0x... address or a Stellar G... address, matching chain
amountBasestringYesAmount in base units

On Stellar, sending to a recipient without an existing trustline for that asset establishes one automatically first (the engine signs for both sides when it custodies the recipient's wallet too).


Approve Spender

Grants an ERC-20 allowance over the user's tokens.

Approve USDT
curl -X POST "http://localhost:8100/api/v1/assets/usdt/approve" \
  -H "Content-Type: application/json" \
  -H "X-Service-Token: YOUR_TOKEN_HERE" \
  -d '{"externalUserId": "123", "spender": "0xSpenderAddress", "amountBase": "1000000"}'
Response200
{ "txHash": "0x...", "chain": "celo", "symbol": "USDT" }

If spender is omitted, defaults to the platform relayer address.

EVM only

Stellar has no allowance/approval concept — ?chain=stellar (or any non-EVM chain) returns 501 asset approval is not yet supported on "stellar" chains. Use Burn (Holder) instead, which needs no prior approval on any chain.


Burn (Relayer)

Burns tokens from a user who has approved the relayer. Used for swap-back flows.

Burn USDT (Relayer)
curl -X POST "http://localhost:8100/api/v1/assets/usdt/burn" \
  -H "Content-Type: application/json" \
  -H "X-Service-Token: YOUR_TOKEN_HERE" \
  -d '{"externalUserId": "123", "amountBase": "5000000", "externalId": "burn-001"}'
Response200
{ "txHash": "0x...", "chain": "celo", "symbol": "USDT", "amount": 5 }

EVM only

Same allowance dependency as Approve above — ?chain=stellar returns 501 burn-from-holder is not yet supported on "stellar" chains — use /assets/usdt/burn-by-holder instead. Use Burn (Holder) on Stellar.


Burn (Holder)

Burns tokens held by the user's own custodial wallet using the user's sealed key — no prior allowance required. Used when redeeming tokens for real-world value (e.g. burning IMC when airtime is delivered).

Burn IMC (Holder)
curl -X POST "http://localhost:8100/api/v1/assets/imc/burn-by-holder" \
  -H "Content-Type: application/json" \
  -H "X-Service-Token: YOUR_TOKEN_HERE" \
  -d '{"externalUserId": "123", "amountBase": 3000000, "externalId": "burn-001"}'
Response200
{ "txHash": "0x...", "chain": "celo", "symbol": "IMC", "amount": 3 }

Request Fields:

FieldTypeRequiredDescription
externalUserIdstringYesUser whose wallet holds the tokens
amountBasenumberYesAmount in base units
externalIdstringYesIdempotency key

Backing-aware accounting

For airtime-backed assets, the burn credits the tenant's airtime inventory account — keeping on-chain supply pegged to real float.

This is the only burn endpoint that works on both EVM and Stellar chains — the recommended default unless you specifically need relayer-initiated burns on an EVM chain.


Admin Asset Management

Register New Asset

Register Asset (Celo)
curl -X POST "http://localhost:8100/api/v1/admin/assets/IMC/register?chain=celo" \
  -H "Content-Type: application/json" \
  -H "X-Service-Token: YOUR_TOKEN_HERE" \
  -d '{"contract": "0xF150E30B1C7Ab81938d650567D1454Ee0132d5A2", "decimals": 6, "name": "ImpalaCoin", "type": "airtime", "backing": "airtime"}'
Response200
{ "message": "asset IMC registered on celo", "asset": { "symbol": "IMC", "contract": "0xF150...d5A2" } }
Register Asset (Stellar)
curl -X POST "http://localhost:8100/api/v1/admin/assets/USDX/register?chain=stellar" \
  -H "Content-Type: application/json" \
  -H "X-Service-Token: YOUR_TOKEN_HERE" \
  -d '{"contract": "GISSUERADDRESSXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", "decimals": 7, "name": "USD Stellar Token", "type": "utility"}'
Response200
{ "message": "asset USDX registered on stellar", "asset": { "symbol": "USDX", "contract": "GISSUER..." } }

On Stellar, contract is the asset's issuer account address (G...), not a contract address — Stellar assets are identified by (asset code, issuer), not a deployed contract.

Deregister Asset

Deregister Asset
curl -X DELETE "http://localhost:8100/api/v1/admin/assets/mytoken?chain=celo" \
  -H "Content-Type: application/json" \
  -H "X-Service-Token: YOUR_TOKEN_HERE"
Response200
{ "message": "asset mytoken deregistered from celo" }

Released under the MIT License.