Skip to Content
Welcome to RitoSwap's documentation!
dAppAPIToken Status

Token Status API

The Token Status API provides real-time information about Colored Key NFT existence and usage within the RitoSwap ecosystem. It powers UI states like “Available”, “Already used for access”, or “Token doesn’t exist” without forcing the frontend to hit the chain directly.

This endpoint is optimized for frequent polling from the dApp UI.

Use this page for a high-level understanding of how token status works. For full request/response schema and example payloads, see the OpenAPI Reference section below.

What this endpoint tracks

Each token has two distinct states:

  1. On-chain existence
    Whether the token has been minted and exists in the Key NFT smart contract.

  2. Off-chain usage
    Whether the token has already been used to access gated content, along with who used it and when.

The API combines these into a single JSON response so the dApp can render token state with one call.

At a high level, the backend does:

  1. Check the database for an existing token record (including usage info).
  2. If missing, hit the chain once to verify existence.
  3. If it exists on-chain but not in the DB, create a record (unused).
  4. Return the combined state back to the client.

This keeps the UI snappy while avoiding unnecessary chain reads.

Endpoint summary

PropertyValue
URL/api/token-status/[tokenId]
MethodGET
URL ParameterstokenId – The NFT token ID to check (non-negative integer)
AuthenticationNone (public endpoint)
Typical UsageReal-time UI checks when viewing tokens or attempting gated access

Network-Aware Database Operations

This API leverages RitoSwap’s sophisticated network routing infrastructure to ensure all operations target the correct blockchain network and corresponding database table. The system automatically handles network detection and routing, allowing the API to work seamlessly across Ethereum mainnet, Sepolia testnet, and local RitoNet development networks.

Automatic Network Routing

The API uses two key utilities from the prismaNetworkUtils module to handle multichain operations:

Database Operations via getTokenModel()
This function returns a unified interface that automatically routes database queries to the correct network-specific table:

import { getTokenModel } from '@/app/lib/prisma/prismaNetworkUtils' const tokenModel = getTokenModel() // Automatically queries token_ethereum, token_sepolia, or token_ritonet const token = await tokenModel.findUnique({ where: { tokenId } })

Blockchain Configuration via getChainConfig()
This function provides the correct RPC endpoints and chain metadata for the active network:

import { getChainConfig } from '@/app/lib/prisma/prismaNetworkUtils' import { createPublicClient, http } from 'viem' const chainConfig = getChainConfig() const publicClient = createPublicClient({ chain: chainConfig.chain, transport: http(chainConfig.transport) })

Network Detection

The active network is defined by the single NEXT_PUBLIC_ACTIVE_CHAIN environment variable (ethereum, sepolia, or ritonet). For local development, additional metadata (NEXT_PUBLIC_LOCAL_CHAIN_ID, RPC/WSS URLs, etc.) must also be provided so the helpers can construct a viable viem client.

Cross-Network Isolation

Each blockchain network maintains its own isolated database table with identical structure:

  • Ethereum Mainnettoken_ethereum table
  • Sepolia Testnettoken_sepolia table
  • RitoNet Localtoken_ritonet table

This isolation prevents cross-network data conflicts while enabling network-specific optimizations and simplified debugging. The same token ID can exist on different networks representing entirely different assets, and this architecture ensures they never interfere with each other.

The network routing happens transparently to the API logic. Developers write network-agnostic code while the infrastructure handles proper routing behind the scenes. For detailed information about the network utilities, see the Network-Aware Database Utils documentation.

Response shape (high-level)

All valid requests (with a valid numeric tokenId) return HTTP 200, even if the token does not exist. The presence and state of the token are communicated via the JSON fields:

interface TokenStatusResponse { count: number; // 1 if the token exists, 0 if it does not exists: boolean; // true if the token exists on-chain used: boolean; // true if it has been used for gating usedBy: string | null; // address that used it (if used) usedAt: string | null; // ISO timestamp of usage (if used) }

Typical results:

  • Token exists and unused
    exists: true, used: false, usedBy: null, usedAt: null

  • Token exists and used
    exists: true, used: true, usedBy and usedAt populated

  • Token does not exist
    exists: false, used: false, count: 0

Use exists and used as your primary flags in the UI.

Minimal request example

A simple fetch from the dApp:

// Check status of token #42 async function getTokenStatus(tokenId: number) { const res = await fetch(`/api/token-status/${tokenId}`); if (!res.ok) { // See “Error behavior” below for details throw new Error(`Failed to check token status: ${res.status}`); } const data = (await res.json()) as { count: number; exists: boolean; used: boolean; usedBy: string | null; usedAt: string | null; }; return data; }

Example usage in a React component:

function TokenStatusBadge({ tokenId }: { tokenId: number }) { const [status, setStatus] = React.useState<null | { exists: boolean; used: boolean; }>(null); React.useEffect(() => { getTokenStatus(tokenId) .then((data) => setStatus({ exists: data.exists, used: data.used })) .catch(() => setStatus(null)); }, [tokenId]); if (!status) return <span>Checking…</span>; if (!status.exists) return <span>Does not exist</span>; if (status.used) return <span>Used</span>; return <span>Available</span>; }

Error behavior & rate limiting

This endpoint distinguishes between:

  • Validation errors (400)
    Returned when tokenId is missing, negative, or not a valid number.

  • Rate limiting (429)
    Returned when a client exceeds the allowed request rate.
    The response includes headers like:

    • X-RateLimit-Limit
    • X-RateLimit-Remaining
    • Retry-After

    Use Retry-After to back off polling intervals.

  • Internal errors (500)
    Returned when something unexpected happens while checking status (e.g. DB connectivity issues, RPC failures, etc.).

For exact JSON shapes and full header definitions, rely on the OpenAPI reference below.

Polling guidelines

The endpoint is designed to handle real-time UI polling, but you should still be polite:

  • Poll more frequently while a token is in a “pending” or “unknown” state.
  • Slow down or stop polling once:
    • the token is marked as used, or
    • the user navigates away / the tab is hidden.

A simple pattern is:

  • 3–5 second interval while waiting for on-chain actions to settle.
  • Back off if you receive 429 and respect the Retry-After header.
  • Stop polling once used === true if that’s a terminal state for your flow.

OpenAPI Reference

For full request/response schema, enums, example payloads, and all status codes, use the generated OpenAPI docs filtered to this tag:

RitoSwap Docs does not store, collect or access any of your conversations. All saved prompts are stored locally in your browser only.