SDK Reference

All symbols are importable from the bare package name. Your bundler or runtime resolves the correct entry automatically via conditional exports.

import { configureApi, getSDKInfo, SDK_NAME, SDK_VERSION, api } from '@coin-communities/sdk';

For React apps, @coin-communities/sdk/react-query re-exports everything below plus pre-baked hooks. See the React Query page.


Functions

configureApi()

Configures the shared HTTP client used by all api.* functions. Call this once at application startup — typically before any API call is made.

Signature

function configureApi(options: ConfigureApiOptions): void

Parameters

Example

import { configureApi } from '@coin-communities/sdk';
 
configureApi({
  baseUrl: 'https://api.coin-communities.xyz',
  headers: { 'x-api-key': 'YOUR_API_KEY' },
});

baseUrl is the API origin. The generated client paths already include /api/v1/..., so don't append it.


getSDKInfo()

Returns metadata describing the SDK and the runtime it was bundled for.

Signature

function getSDKInfo(): SDKInfo

Platform-divergent behaviour — the platform field reflects the conditional export resolved at bundle time.

Runtimeplatform value
Browser (React)'react'
React Native'react-native'
Node.js / default'node'

Returns SDKInfo

Example

import { getSDKInfo } from '@coin-communities/sdk';
 
const info = getSDKInfo();
// { name: '@coin-communities/sdk', version: '0.0.8', platform: 'react' }

Authentication

The API uses two authentication schemes. Configure the right one via configureApi.

API key (x-api-key)

Most read and write operations on communities, users, and the feed accept an API key sent as the x-api-key request header. Create a key in the business dashboard or via api.createApiKey().

configureApi({
  baseUrl: 'https://api.coin-communities.xyz',
  headers: { 'x-api-key': process.env.CC_API_KEY },
});

Bearer JWT (Authorization: Bearer)

Business management operations (API keys, members, callbacks, audit logs) require a JWT obtained by calling api.login() with business email + password credentials.

configureApi({
  baseUrl: 'https://api.coin-communities.xyz',
  auth: () => sessionStorage.getItem('token') ?? '',
});

Set auth to a function returning the JWT string. It is called per-request and may be async. If you need both schemes simultaneously, put the API key in headers and the JWT in auth.

Server key + secret (x-server-key / x-server-secret)

The *Server operations (see Community — Server-side operations) authenticate with a server API key pair rather than an API key or JWT. Both headers are required and must never be shipped to a browser. Mint a pair with api.createServerApiKey().

configureApi({
  baseUrl: 'https://api.coin-communities.xyz',
  headers: {
    'x-server-key': process.env.CC_SERVER_KEY,
    'x-server-secret': process.env.CC_SERVER_SECRET,
  },
});

Unauthenticated endpoints

Only the platform health probes require no authentication:

EndpointDescription
GET /healthLiveness check
GET /pingLatency probe

The */public operations (getTopCommunities, getMessagesPublic, getFeedPublic) read data anonymously — they don't need a user JWT — but they still require an x-api-key. Pass it via configureApi({ headers: { 'x-api-key': ... } }).


Types

ConfigureApiOptions

Options accepted by configureApi().

type ConfigureApiOptions = Pick<Config, 'baseUrl' | 'fetch' | 'headers' | 'auth'>;

Fields

  • baseUrl (string) — API origin. Defaults to 'https://api.coin-communities.xyz'. Don't include /api/v1 — operation paths already carry it.
  • fetch (typeof globalThis.fetch) — custom fetch implementation. Useful in environments where you need a polyfill or want to intercept requests.
  • headers (HeadersInit) — default headers merged into every request. Use this to pass x-api-key.
  • auth (string | ((auth: Auth) => string | undefined | Promise<string | undefined>)) — bearer token or a function (sync or async) that returns one. Attached to each request that declares jwt_auth security.

SDKInfo

The object shape returned by getSDKInfo().

interface SDKInfo {
  name: string;
  version: string;
  platform: Platform;
}

Platform

type Platform = 'react' | 'react-native' | 'node';
ValueResolved when
'react'Bundled for browser environments (the browser conditional export)
'react-native'Bundled for React Native (the react-native conditional export)
'node'Running in Node.js or when no other condition matches (default)

Constants

SDK_NAME

const SDK_NAME: string

The package name string. Value: '@coin-communities/sdk'.


SDK_VERSION

const SDK_VERSION: string

The current SDK version string.


HTTP API (api.*)

All generated API operations are exported as a namespace called api. Configure the client once with configureApi(), then call operations directly.

Call pattern

By default operations return { data, error, response }. Pass { throwOnError: true } to throw on HTTP errors instead.

import { configureApi, api } from '@coin-communities/sdk';
 
configureApi({
  baseUrl: 'https://api.coin-communities.xyz',
  headers: { 'x-api-key': 'YOUR_KEY' },
});
 
const { data, error } = await api.getCommunity({
  path: { token_address: '7eYw...' },
});
 
if (error) {
  console.error('failed', error.message);
} else {
  console.log(data.community.tokenAddress);
}

Operations that take a request body, path params, or query params accept them under the matching keys:

// Path params
await api.getCommunity({ path: { token_address: '7eYw...' } });
 
// Query params
await api.getMessages({ path: { token_address: '7eYw...' }, query: { limit: 50 } });
 
// Body
await api.postMessage({
  path: { token_address: '7eYw...' },
  body: { content: 'gm', chainId: 'solana', walletAddress: 'YourWalletPubkey' },
});

Type names

The generated types follow each operation's name. For an operation xxx() you get:

  • XxxData — request shape (body / path / query / url)
  • XxxResponses — map of status code → response body
  • XxxResponse — union of success response bodies
  • XxxErrors — map of status code → error body
  • XxxError — union of error bodies (where applicable)

Refer to types.gen.ts and openapi.json in the SDK package for the full schema.


Operations by domain

Diagnostics

OperationHTTPAuthDescription
healthGET /healthnoneLiveness check. Returns { status: 'ok' }.
pingGET /pingnoneLatency probe.

Business — Auth

Manages business accounts (the team-level entity that owns API keys, callbacks, and members). Business endpoints use email + password credentials; calls return a JWT used as the bearer token.

OperationHTTPAuthDescription
meGET /api/v1/business/mejwtReturns the authenticated business profile.
loginPOST /api/v1/business/loginnoneEmail + password login. Returns a JWT.
logoutPOST /api/v1/business/logoutjwtInvalidates the current session.
registerPOST /api/v1/business/registernoneCreate a new business account.
verifyEmailPOST /api/v1/business/verify-emailnoneConfirm email via verification code.
resendVerificationPOST /api/v1/business/resend-verificationnoneRe-send verification email.
forgotPasswordPOST /api/v1/business/forgot-passwordnoneTrigger password-reset email.
resetPasswordPOST /api/v1/business/reset-passwordnoneComplete password reset with code.

Business — API Keys

OperationHTTPAuthDescription
getApiKeysGET /api/v1/business/api-keysjwtList API keys for the business.
createApiKeyPOST /api/v1/business/api-keysjwtCreate a new API key (key shown once).
rotateApiKeyPOST /api/v1/business/api-keys/{id}/rotatejwtRotate an API key's secret.
revokeApiKeyDELETE /api/v1/business/api-keys/{id}jwtRevoke an API key permanently.
listApiKeyOriginsGET /api/v1/business/api-keys/{id}/originsjwtList allowed browser origins for an API key.
addApiKeyOriginPOST /api/v1/business/api-keys/{id}/originsjwtAdd an allowed origin. Returns 409 if already present.
removeApiKeyOriginDELETE /api/v1/business/api-keys/{id}/origins/{origin_id}jwtRemove an allowed origin.

Business — Server API Keys

Server API keys authenticate server-side operations that bypass per-user context — e.g. reading all messages across communities from a backend. They are distinct from regular API keys and are not usable in browser contexts. Each key is a pair: the x-server-key identifier and a matching x-server-secret, both of which must be sent on every server-side request.

OperationHTTPAuthDescription
getServerApiKeysGET /api/v1/business/server-api-keysjwtList server API keys for the business.
createServerApiKeyPOST /api/v1/business/server-api-keysjwtCreate a new server API key. Returns key and secret once — store them immediately.
revokeServerApiKeyDELETE /api/v1/business/server-api-keys/{id}jwtRevoke a server API key permanently.

Business — Callbacks

Webhook URLs the platform POSTs to on community events.

OperationHTTPAuthDescription
listCallbacksGET /api/v1/business/callbacksjwtList registered callback URLs.
addCallbackPOST /api/v1/business/callbacksjwtRegister a callback URL.
removeCallbackDELETE /api/v1/business/callbacks/{id}jwtRemove a callback URL.

Business — Members

OperationHTTPAuthDescription
getMembersGET /api/v1/business/membersjwtList team members.
addMemberPOST /api/v1/business/membersjwtInvite a new team member by email.
deleteMemberDELETE /api/v1/business/members/{id}jwtRemove a team member.

Business — Logs

OperationHTTPAuthDescription
getLogsGET /api/v1/business/logsjwtRead API call audit logs. Accepts GetLogsParams query filters.

Communities

A community is keyed by its on-chain token_address. Most community operations accept either jwt_auth or api_key_auth.

OperationHTTPAuthDescription
getTopCommunitiesGET /api/v1/communities/topnoneList top communities by activity.
getCommunityGET /api/v1/communities/{token_address}api keyFetch community metadata.
getMessagesGET /api/v1/communities/{token_address}/messagesapi keyList messages. Accepts GetMessagesQuery.
getMessagesPublicGET /api/v1/communities/{token_address}/messages/publicnoneRead messages without authentication.
postMessagePOST /api/v1/communities/{token_address}/messagesapi keyPost a new message. Requires body PostMessageRequest.
likeMessagePOST /api/v1/communities/{token_address}/messages/{message_id}/likeapi keyLike a message.
unlikeMessageDELETE /api/v1/communities/{token_address}/messages/{message_id}/likeapi keyRemove a like.
getLikeCountGET /api/v1/communities/{token_address}/messages/{message_id}/likesapi keyRead the like count for a message.
getRepliesGET /api/v1/communities/{token_address}/messages/{message_id}/repliesapi keyList replies. Accepts GetRepliesQuery.
postReplyPOST /api/v1/communities/{token_address}/messages/{message_id}/repliesapi keyPost a reply. Body shape identical to postMessage.
reportMessagePOST /api/v1/communities/{token_address}/messages/{message_id}/reportapi keyReport a message. Accepts ReportMessageRequest.
getCommunityMembersGET /api/v1/communities/{token_address}/membersapi keyList members. Accepts limit and offset query params.
getWsTicketPOST /api/v1/communities/{token_address}/ws/ticketapi keyObtain a short-lived WebSocket ticket for realtime subscriptions.
getCommunitiesBatchPOST /api/v1/communities/batchapi keyFetch multiple communities in a single request. Body: BatchGetCommunitiesRequest.
getMessagePublicGET /api/v1/communities/messages/{message_id}/publicapi keyFetch a single message by ID without a user session. Returns PublicMessageResponse.

Community — Server-side operations

These operations authenticate with the x-server-key + x-server-secret pair (see Business — Server API Keys). They are intended for trusted server environments and are not safe to call from browsers. Server-side write operations (postMessageServer, postReplyServer) accept a twitterId in the body to attribute the post to a user without that user's JWT.

OperationHTTPAuthDescription
getMessagesServerGET /api/v1/communities/{token_address}/messages/serverserver key + secretRead all messages (including moderation metadata) for a community.
postMessageServerPOST /api/v1/communities/{token_address}/messages/serverserver key + secretPost a message on behalf of a user. Body: PostMessageServerRequest.
getRepliesServerGET /api/v1/communities/{token_address}/messages/{message_id}/replies/serverserver key + secretRead all replies for a message (including moderation metadata).
postReplyServerPOST /api/v1/communities/{token_address}/messages/{message_id}/replies/serverserver key + secretPost a reply on behalf of a user. Body: PostMessageServerRequest.
getCommunityMembersServerGET /api/v1/communities/{token_address}/members/serverserver key + secretList contributing members for a community. Accepts limit and offset query params.
getMessagesGlobalServerGET /api/v1/communities/messages/serverserver key + secretRead messages across all communities. Accepts GetGlobalMessagesQuery.
getWsTicketServerPOST /api/v1/communities/{token_address}/ws/ticket/serverserver key + secretObtain a WebSocket ticket scoped to a single community for server-side subscriptions.
getWsTicketGlobalServerPOST /api/v1/communities/ws/ticket/server/globalserver key + secretObtain a global WebSocket ticket for server-side subscriptions.

Community media

OperationHTTPAuthDescription
uploadCommunityMediaPOST /api/v1/communities/mediaapi keyUpload an image for use in a message. Returns a media URL.
getMediaProvidersGET /api/v1/communities/media-providersapi keyList supported upload providers.
getSupportedChainsGET /api/v1/communities/chainsapi keyList blockchain networks the platform supports.

Feed

OperationHTTPAuthDescription
getFeedGET /api/v1/feedapi keyCross-community activity feed (authenticated).
getFeedPublicGET /api/v1/feed/publicnoneCross-community activity feed without authentication.

Users

End-user (not business) profile management. Users authenticate via Twitter OAuth — see Twitter.

OperationHTTPAuthDescription
userMeGET /api/v1/users/meapi keyReturns the authenticated user profile.
refreshTokenPOST /api/v1/users/token/refreshapi keyExchange a refresh token for a new access token.
getUserCommunitiesGET /api/v1/users/{user_id}/communitiesapi keyList communities a user belongs to. Accepts limit and offset query params.
getUserByWalletGET /api/v1/users/by-wallet/{address}api keyLook up a user by a linked wallet address.
getUserIdByTwitterIdGET /api/v1/users/by-twitter-id/{twitter_id}api keyResolve a Twitter ID to its platform userId.
getUsersByWalletBatchPOST /api/v1/users/by-wallet/batchapi keyLook up multiple users by wallet addresses in one request. Body: BatchGetUsersByWalletRequest.

Wallets

Link EVM and Solana wallets to a user account via a signed challenge.

OperationHTTPAuthDescription
getWalletsGET /api/v1/users/me/walletsapi keyList linked wallets.
walletChallengePOST /api/v1/users/me/wallets/challengeapi keyRequest a sign-in challenge for the wallet.
linkWalletPOST /api/v1/users/me/walletsapi keyLink a wallet using the signed challenge nonce.
unlinkWalletDELETE /api/v1/users/me/wallets/{id}api keyUnlink a wallet.

Twitter

User authentication flows. These endpoints require api_key_auth.

OperationHTTPAuthDescription
twitterAuthUrlGET /api/v1/users/twitter/auth-urlapi keyGet the Twitter OAuth authorization URL.
twitterCallbackPOST /api/v1/users/twitter/callbackapi keyComplete the OAuth flow (legacy token-in-redirect path).
twitterChallengeExchangePOST /api/v1/users/twitter/challenge/exchangeapi keyExchange a one-time challengeCode for access + refresh tokens. Preferred over twitterCallback.

User social graph

OperationHTTPAuthDescription
getUserProfileGET /api/v1/users/{user_id}/profileapi keyFetch a user's public profile.
getFollowersGET /api/v1/users/{user_id}/followersapi keyList a user's followers. Accepts limit and offset.
getFollowingGET /api/v1/users/{user_id}/followingapi keyList users that a user follows.
followUserPOST /api/v1/users/{user_id}/followapi keyFollow a user.
unfollowUserDELETE /api/v1/users/{user_id}/followapi keyUnfollow a user.

Short links

Short-link operations create and resolve opaque link codes for sharing community pages or individual posts. Link codes are scoped to the community identified by tokenAddress.

OperationHTTPAuthDescription
createLinkPOST /api/v1/linksapi keyCreate (or return an existing) short link for a community or post. Body: CreateLinkRequest. Returns LinkResponse.
resolveLinkGET /api/v1/links/{code}api keyResolve an opaque short-link code back to its target. Returns LinkResponse.

Realtime

The SDK ships a WebSocket client for live community updates.

// Resolved automatically when bundled for browser or React Native
import { CommunityRealtimeClient } from '@coin-communities/sdk';
// or explicit subpath
import { CommunityRealtimeClient } from '@coin-communities/sdk/react';
import { CommunityRealtimeClient } from '@coin-communities/sdk/react-native';

The realtime module is not available in the node condition. CommunityRealtimeClient, useCommunityEvents, useCommunityRealtime, realtimeAuthFromApiClient, and bindCommunityEventsToQueryClient are exported only from the browser (react) and react-native entry points. In Node.js, import from @coin-communities/sdk/react or @coin-communities/sdk/react-native explicitly, or use the raw WebSocket API.

CommunityRealtimeClient

A shared WebSocket client per (baseUrl, tokenAddress) pair. Call getOrCreate to get or lazily spin up a connection; CommunityRealtimeClient handles reconnection with exponential back-off automatically.

const client = CommunityRealtimeClient.getOrCreate({
  baseUrl: 'https://api.coin-communities.xyz',
  tokenAddress: '7eYw...',
  auth: {
    // Fetches a fresh single-use ticket on connect and every reconnect.
    getTicket: async () => {
      const { data } = await api.getWsTicket({ path: { token_address: '7eYw...' } });
      if (!data?.ticket) throw new Error('WebSocket ticket unavailable');
      return data.ticket;
    },
  },
});
 
const dispose = client.subscribe({
  onMessage:    (event) => console.log('message persisted', event),
  onModeration: (event) => console.log('moderation update', event),
  onLike:       (event) => console.log('like update', event),
  onGap:        () => console.log('reconnected — refetch via REST'),
  onConnect:    () => console.log('connected'),
  onDisconnect: () => console.log('disconnected'),
});
 
// Later:
dispose(); // unsubscribe this handler (connection shared with other subscribers)

useCommunityEvents (React hook)

import { useCommunityEvents } from '@coin-communities/sdk';
 
useCommunityEvents(tokenAddress, {
  auth: { getTicket: async () => /* return ws ticket string */ },
  onMessage:    (event) => { /* message persisted */ },
  onModeration: (event) => { /* spam/harmful flags changed */ },
  onLike:       (event) => { /* like update */ },
  onGap:        () => { /* reconnected — refetch via REST */ },
});

The hook wires up and tears down the subscription with the component lifecycle. Handler callbacks are wrapped in refs so you can pass inline functions without churning the connection.

Because posts are processed asynchronously, onMessage is how you confirm a submitted post was persisted, and onModeration is how you learn it was later flagged. See Realtime events for the useOptimisticCommunityPosts hook and the lower-level reconciliation recipe.


useCommunityRealtime (React hook)

A thinner counterpart to useCommunityEvents. Instead of accepting event handlers, it exposes the most recent event envelope and the current connection status, letting you react in JSX rather than callbacks.

Signature

function useCommunityRealtime(
  tokenAddress: string,
  options?: UseCommunityRealtimeOptions,
): { lastEvent: RealtimeEvent | null; status: RealtimeStatus }

Example

import { useCommunityRealtime } from '@coin-communities/sdk';
 
function ConnectionBadge({ tokenAddress }: { tokenAddress: string }) {
  const { status, lastEvent } = useCommunityRealtime(tokenAddress, {
    auth: async () => { /* return ws ticket */ },
  });
 
  return <span>{status === 'open' ? '🟢' : '🔴'} {lastEvent?.type}</span>;
}

realtimeAuthFromApiClient

Builds a RealtimeGetTicketAuth by fetching a fresh WebSocket ticket via the SDK's generated REST client. The JWT (Authorization) and/or x-api-key already configured on the client are forwarded to the ticket endpoint automatically.

Signature

function realtimeAuthFromApiClient(
  client: Client,
  tokenAddress: string,
): RealtimeGetTicketAuth

Example

import { realtimeAuthFromApiClient, CommunityRealtimeClient } from '@coin-communities/sdk';
import { createClient } from '@hey-api/client-fetch';
 
const httpClient = createClient({ baseUrl: 'https://api.coin-communities.xyz' });
const auth = realtimeAuthFromApiClient(httpClient, '7eYw...');
 
const rtClient = CommunityRealtimeClient.getOrCreate({
  baseUrl: 'https://api.coin-communities.xyz',
  tokenAddress: '7eYw...',
  auth,
});

bindCommunityEventsToQueryClient

Wires a CommunityRealtimeClient into a TanStack Query QueryClient, automatically invalidating and patching cache entries as realtime events arrive. Useful in scenarios where you want live cache updates without mounting a React component.

Signature

function bindCommunityEventsToQueryClient(
  queryClient: QueryClient,
  tokenAddress: string,
  options?: { baseUrl?: string; auth?: RealtimeAuth },
): () => void

Returns an unsubscribe function.

Example

import { bindCommunityEventsToQueryClient } from '@coin-communities/sdk';
import { QueryClient } from '@tanstack/react-query';
 
const qc = new QueryClient();
const unsubscribe = bindCommunityEventsToQueryClient(qc, '7eYw...', {
  baseUrl: 'https://api.coin-communities.xyz',
  auth: { getTicket: async () => (await api.getWsTicket({ path: { token_address: '7eYw...' } })).data?.ticket ?? '' },
});
 
// Later:
unsubscribe();

Realtime types

These types are exported from the browser and react-native conditions (via the realtime namespace). They are not available from the node condition without an explicit subpath import.

RealtimeAuth

Union of the two supported authentication modes.

type RealtimeAuth = RealtimeGetTicketAuth | RealtimeStaticTicketAuth;

RealtimeGetTicketAuth

Preferred production auth: fetches a fresh single-use WebSocket ticket before each connection attempt (and every reconnect). The ticket is obtained via api.getWsTicket and is consumed server-side on the first connection.

interface RealtimeGetTicketAuth {
  getTicket: () => Promise<string>;
}

RealtimeStaticTicketAuth

Static ticket — suitable for tests or one-shot connections. Tickets are single-use server-side, so reconnects with this mode will fail with 401 Invalid or expired ticket. Prefer RealtimeGetTicketAuth in production.

interface RealtimeStaticTicketAuth {
  ticket: string;
}

RealtimeHandlers

Subscriber-supplied event handlers. All fields are optional.

interface RealtimeHandlers {
  onMessage?:    (e: CommunityMessageEvent) => void;
  onLike?:       (e: LikeUpdatePayload) => void;
  onModeration?: (e: ModerationUpdatePayload) => void;
  onGap?:        () => void;
  onConnect?:    () => void;
  onDisconnect?: () => void;
}
  • onMessage — fired when a new (or updated) message event arrives on the wire.
  • onLike — fired when a like count changes.
  • onModeration — fired when a message's isSpam / isHarmful flags change.
  • onGap — fired exactly once per reconnect gap: signals that events may have been missed and the consumer should refetch via REST.
  • onConnect / onDisconnect — connection lifecycle events.

RealtimeEvent

Discriminated union of wire-level event envelopes.

type RealtimeEvent =
  | { eventType: 'message_update'; data: CommunityMessageEvent }
  | { eventType: 'like_update';    data: LikeUpdatePayload }
  | { eventType: 'moderation_update'; data: ModerationUpdatePayload };

RealtimeEventTypes

String constant map for the three wire-level event discriminants. Use these instead of raw strings to avoid typos.

const RealtimeEventTypes = {
  MessageUpdate:    'message_update',
  LikeUpdate:       'like_update',
  ModerationUpdate: 'moderation_update',
} as const;

RealtimeEventType

Union of the three wire discriminant strings.

type RealtimeEventType = 'message_update' | 'like_update' | 'moderation_update';

RealtimeStatus

Connection lifecycle state surfaced by useCommunityRealtime.

type RealtimeStatus = 'connecting' | 'open' | 'closed';

CommunityMessageEvent

Payload of a message_update WebSocket event. Mirrors the backend CommunityMessageEvent struct. Notable omissions vs the REST Message type: likeCount, replyCount, and tokenAddress are not present on the broadcast event.

interface CommunityMessageEvent {
  id: string;
  communityId: string;
  businessId: string;
  userId: string;
  username: string;
  userTwitterUrl: string;
  profileImageUrl: string | null;
  followerCount: number;
  content: string;
  mediaUrl: string | null;
  isSpam: boolean;
  isHarmful: boolean;
  createdAt: string;
  parentMessageId: string | null; // non-null when this is a reply
}

LikeUpdatePayload

Payload of a like_update WebSocket event.

interface LikeUpdatePayload {
  messageId: string;
  liked: boolean; // true = like added; false = like removed
}

ModerationUpdatePayload

Payload of a moderation_update WebSocket event — fired when a message's spam/harmful classification changes.

interface ModerationUpdatePayload {
  messageId: string;
  communityId: string;
  isSpam: boolean;
  isHarmful: boolean;
}

RealtimeClientOptions

Options accepted by the CommunityRealtimeClient constructor (and getOrCreate).

interface RealtimeClientOptions {
  baseUrl: string;
  tokenAddress: string;
  auth?: RealtimeAuth;
  reconnectBaseMs?: number;  // default 500ms
  reconnectCapMs?: number;   // default 30 000ms
  heartbeatIntervalMs?: number; // default 0 (disabled — see note below)
  heartbeatTimeoutMs?: number;  // default 10 000ms
}
  • reconnectBaseMs / reconnectCapMs — control the exponential-backoff window for automatic reconnects.
  • heartbeatIntervalMs — application-level ping/pong interval. Disabled by default (0) because the current backend does not echo pong frames; enabling this against an unmodified backend will cause forced reconnects. Opt in only when the backend supports it.

Entity types

Community

type Community = {
  id: string;
  tokenAddress: string;
  createdAt: string;
};
  • id — unique community identifier.
  • tokenAddress — on-chain token mint address that keys this community.
  • createdAt — ISO-8601 creation timestamp.

TopCommunity

Returned by getTopCommunities.

type TopCommunity = {
  tokenAddress: string;
  tokenSymbol: string;
  tokenImageUrl?: string | null;
  tokenHighResImageUrl?: string | null;
  chainId?: number | null;
  memberCount: number;
  postCount: number;
  totalLikes: number;
  latestPostAt: number; // Unix ms
};
  • tokenHighResImageUrl — higher-resolution variant of tokenImageUrl, when available.
  • chainId — numeric chain identifier for the token's network.

Message

A community message posted by a user.

type Message = {
  id: string;
  communityId: string;
  businessId: string;
  userId: string;
  tokenAddress: string;
  content: string;
  mediaUrl?: string | null;
  walletAddress?: string | null;
  username: string;
  displayName: string;
  userTwitterUrl: string;
  profileImageUrl?: string | null;
  followerCount: number;
  likeCount: number;
  liked: boolean;
  replyCount: number;
  parentMessageId?: string | null;
  isSpam: boolean;
  isHarmful: boolean;
  source?: string | null;
  deletedAt?: string | null;
  deletedReason?: string | null;
  createdAt: string;
};
  • walletAddress — the wallet the message was posted from; may be null for messages posted via server-side operations.
  • displayName — the user's display name at the time the message was posted.
  • liked — whether the currently authenticated user has liked this message.
  • parentMessageId — non-null when this message is a reply.
  • isSpam / isHarmful — server-side content classification flags.
  • source — optional label identifying the posting surface (e.g. embed).
  • deletedAt / deletedReason — set when the message has been soft-deleted.

FeedItem

A cross-community feed entry returned by getFeed / getFeedPublic.

type FeedItem = {
  id: string;
  communityId: string;
  tokenAddress: string;
  tokenSymbol?: string | null;
  tokenImageUrl?: string | null;
  content: string;
  mediaUrl?: string | null;
  username: string;
  displayName: string;
  profileImageUrl?: string | null;
  userTwitterUrl: string;
  walletAddress?: string | null;
  followerCount: number;
  likeCount: number;
  liked?: boolean | null;
  replyCount: number;
  source?: string | null;
  createdAt: string;
};
  • displayName — the user's display name at feed-computation time.
  • walletAddress — the wallet the post was attributed to, when available.
  • liked — present only in the authenticated feed (getFeed); null/absent in the public feed.
  • source — optional label identifying the posting surface.

User

An end-user (community participant), authenticated via Twitter OAuth.

type User = {
  id: string;
  twitterId: string;
  username: string;
  profileImageUrl?: string | null;
  followerCount: number;
  followerCountSyncedAt?: string | null;
  nativeFollowerCount: number;
  nativeFollowingCount: number;
  createdAt: string;
};
  • followerCount — Twitter follower count (synced periodically).
  • nativeFollowerCount / nativeFollowingCount — in-platform social graph counts.

UserProfile

Public profile. Returned by getUserProfile and inside FollowListResponse.

type UserProfile = {
  id: string;
  username: string;
  profileImageUrl?: string | null;
  followerCount: number;
  nativeFollowerCount: number;
  nativeFollowingCount: number;
  createdAt: string;
};

CommunityMember

A community participant. Returned by getCommunityMembers.

type CommunityMember = {
  userId: string;
  username: string;
  displayName: string;
  profileImageUrl?: string | null;
  twitterUrl: string;
  followerCount: number;
  messageCount: number;
};
  • displayName — the member's display name, which may differ from their username.

A wallet address linked to a user account.

type WalletLink = {
  id: string;
  userId: string;
  businessId: string;
  address: string;
  chainType: ChainType;
  createdAt: string;
};

Business

The team-level entity returned by api.me().

type Business = {
  id: string;
  name: string;
  rateLimitPerSecond: number;
  createdAt: string;
};

BusinessUser

A member of a business team. Returned inside MeResponse and GetMembersResponse.

type BusinessUser = {
  id: string;
  businessId: string;
  email: string;
  emailVerified: boolean;
  role: string;
  createdAt: string;
};

ApiKey

type ApiKey = {
  id: string;
  businessId: string;
  createdBy: string;
  name: string;
  keyPrefix: string;
  keyHash: string;
  lastUsedAt?: string | null;
  revokedAt?: string | null;
  createdAt: string;
};

The full key string is only returned once — in the key field of CreateApiKeyResponse or RotateApiKeyResponse. Store it immediately; it cannot be retrieved again.


ServerApiKey

A server-side API key used with x-server-key authentication. Created and managed via the getServerApiKeys / createServerApiKey / revokeServerApiKey operations.

type ServerApiKey = {
  id: string;
  businessId: string;
  createdBy: string;
  name: string;
  keyPrefix: string;
  keyHash: string;
  lastUsedAt?: string | null;
  revokedAt?: string | null;
  createdAt: string;
};

The full key and secret are only returned once — in the key and secret fields of CreateServerApiKeyResponse. Store them immediately; they cannot be retrieved again.


ApiKeyOrigin

An allowed-origin entry for an API key.

type ApiKeyOrigin = {
  id: string;
  apiKeyId: string;
  origin: string;
  createdAt: string;
};

WhitelistedCallback

A registered callback (webhook) URL belonging to a business.

type WhitelistedCallback = {
  id: string;
  businessId: string;
  url: string;
  createdAt: string;
};

MediaProvider

A platform-approved media host. URLs from approved providers are accepted by postMessage.

type MediaProvider = {
  id: string;
  name: string;
  logoUrl: string;
  searchUrl: string;
  domains: string[];
};

ApiLogEvent

A single API call log entry returned by getLogs.

type ApiLogEvent = {
  apiKeyId: string;
  businessId: string;
  method: string;
  path: string;
  statusCode: number;
  latencyMs: number;
  createdAt: string;
};

MessageLike

A record of a user liking a message.

type MessageLike = {
  messageId: string;
  userId: string;
  businessId: string;
  createdAt: string;
};

WsTicketResponse

Returned by getWsTicket, getWsTicketServer, and getWsTicketGlobalServer.

type WsTicketResponse = {
  ticket: string;
};

Pass ticket to RealtimeGetTicketAuth or directly to CommunityRealtimeClient.


Enums

ChainId

type ChainId = 'solana' | 'ethereum' | 'base' | 'bsc';

Identifies the blockchain for a message. Required field in PostMessageRequest.


ChainType

type ChainType = 'evm' | 'svm';

Wallet signing scheme. 'svm' = Solana; 'evm' = Ethereum / EVM-compatible chains. Used in LinkWalletRequest and WalletChallengeRequest.


MessageSortField

type MessageSortField = 'time' | 'likes';

Controls the sort field for getMessages. Default 'time'.


MessageSortOrder

type MessageSortOrder = 'desc' | 'asc';

Sort direction for getMessages. Default 'desc'.


ReportReason

type ReportReason =
  | 'spam'
  | 'harassment'
  | 'hate_speech'
  | 'inappropriate_content'
  | 'other';

Required field in ReportMessageRequest. When 'other', include a text field.


LinkKind

type LinkKind = 'community' | 'post';
ValueDescription
'community'Link targets a community page.
'post'Link targets a specific message within a community.

Response types

LinkResponse

Returned by createLink and resolveLink.

type LinkResponse = {
  code: string;
  kind: LinkKind;
  tokenAddress: string;
  messageId?: string | null;
};
  • code — opaque short-link code. Construct the shareable URL as https://your-app.com/l/${code} and pass the code to resolveLink to retrieve the target.
  • messageId — present when kind === 'post'.

Request and query types

PostMessageRequest

type PostMessageRequest = {
  content: string;                // required
  chainId: ChainId;               // required
  walletAddress: string;          // required — must be a linked wallet
  mediaUrl?: string | null;       // must be a URL from uploadCommunityMedia
  invalidateCache?: boolean | null; // force-refresh wallet-link and balance-eligibility cache before posting
};
  • invalidateCache — when true, drops the server's cached wallet-link and balance-eligibility entries for this wallet before checking, forcing a fresh DB/RPC lookup. Use only when you suspect a stale cache entry is blocking a post.

Errors400 invalid body; 403 wallet not linked or insufficient token balance.


GetMessagesQuery

Query parameters accepted by getMessages.

type GetMessagesQuery = {
  before?: string | null;          // cursor (message id) for time-sorted pagination
  offset?: number | null;          // offset for likes-sorted pagination
  limit?: number | null;           // default 50, max 100
  sort?: MessageSortField | null;  // default 'time'
  order?: MessageSortOrder | null; // default 'desc'
  filterIsSpam?: boolean | null;   // exclude spam-classified messages
  filterIsHarm?: boolean | null;   // exclude harm-classified messages
};

GetRepliesQuery

Query parameters accepted by getReplies.

type GetRepliesQuery = {
  before?: string | null;          // cursor (reply id) for pagination
  limit?: number | null;
  order?: MessageSortOrder | null; // default 'desc'
};

ReportMessageRequest

type ReportMessageRequest = {
  reason: ReportReason;  // required
  text?: string | null;  // required when reason is 'other'
};

GetLogsParams

Query parameters accepted by getLogs.

type GetLogsParams = {
  apiKeyId?: string | null;    // filter to a specific API key
  method?: string | null;      // HTTP method e.g. 'GET'
  path?: string | null;        // request path prefix
  statusClass?: number | null; // 2 = 2xx, 4 = 4xx, 5 = 5xx
  startTime?: string | null;   // ISO-8601 lower bound
  endTime?: string | null;     // ISO-8601 upper bound
  limit?: number;
  offset?: number;             // default 0
};

LinkWalletRequest

type LinkWalletRequest = {
  address: string;      // required — wallet public address
  chainType: ChainType; // required
  signature: string;    // required — signature over the nonce from walletChallenge
};

Errors400 no pending challenge; 401 invalid signature; 409 wallet already linked.


WalletChallengeRequest

type WalletChallengeRequest = {
  address: string;      // required
  chainType: ChainType; // required
};

Returns { message: string; nonce: string }. The wallet must sign the message; pass the resulting signature + address + chainType to linkWallet.


TwitterAuthUrlQuery

type TwitterAuthUrlQuery = {
  redirectUrl: string; // required — must be whitelisted in your business dashboard
};

The server appends either accessToken+refreshToken (legacy) or a one-time challengeCode to the redirect URL. Exchange the code via twitterChallengeExchange.

Errors400 redirectUrl not whitelisted.


TwitterChallengeExchangeRequest

type TwitterChallengeExchangeRequest = {
  challengeCode: string; // single-use, short-lived
};

Returns { accessToken, refreshToken, user }. Errors404 code expired.


UploadMediaRequest

type UploadMediaRequest = {
  contentType: string; // e.g. 'image/jpeg'
  data: string;        // base64-encoded file content
};

Body accepted by uploadCommunityMedia. Returns { mediaUrl: string }.


AddOriginRequest

type AddOriginRequest = {
  origin: string; // e.g. 'https://app.example.com' — no path, no trailing slash
};

Errors404 API key not found; 409 origin already allowed.


BatchGetCommunitiesRequest

Body accepted by getCommunitiesBatch.

type BatchGetCommunitiesRequest = {
  tokenAddresses: string[]; // required — list of on-chain token addresses
};

Returns BatchGetCommunitiesResponse with a results map keyed by token address.


PostMessageServerRequest

Body accepted by postMessageServer and postReplyServer. Identical to PostMessageRequest but attributes the post to a user via twitterId instead of relying on a per-user JWT.

type PostMessageServerRequest = {
  content: string;                  // required
  chainId: ChainId;                 // required
  walletAddress: string;            // required — must be a linked wallet
  twitterId: string;                // required — user to attribute the post to
  invalidateCache?: boolean | null; // drop cached balance-eligibility before posting
};
  • twitterId — the Twitter ID of the user the message is posted on behalf of.
  • invalidateCache — when true, drops the server's cached balance-eligibility entry for this wallet before checking, forcing a fresh RPC/price lookup.

GetGlobalMessagesQuery

Query parameters accepted by getMessagesGlobalServer.

type GetGlobalMessagesQuery = {
  before?: string | null;          // cursor (message id) for backward pagination
  since?: number | null;           // lookback: only messages at/after this unix-ms timestamp
  limit?: number | null;           // default 100, max 500
  order?: MessageSortOrder | null;
  includeReplies?: boolean | null; // include replies alongside root messages (default false)
  filterIsSpam?: boolean | null;
  filterIsHarm?: boolean | null;
};

CreateLinkRequest

Body accepted by createLink.

type CreateLinkRequest = {
  kind: LinkKind;           // required
  tokenAddress: string;     // required — the community token address
  messageId?: string | null; // required when kind is 'post'
};
  • kind'community' for a community page link; 'post' for a link to a specific message.
  • messageId — the message to link to. Must be provided when kind === 'post'.

Errors400 invalid body.


PublicMessageResponse

Returned by getMessagePublic. A stripped-down message shape safe for unauthenticated reads.

type PublicMessageResponse = {
  id: string;
  content: string;
  username: string;
  displayName: string;
  profileImageUrl?: string | null;
  likeCount: number;
  replyCount: number;
};

Errors404 message not found.


BatchGetUsersByWallet

Request

Body accepted by getUsersByWalletBatch.

type BatchGetUsersByWalletRequest = {
  addresses: string[]; // required — wallet public addresses to look up
};

Errors400 empty list or too many addresses.

Response

type BatchGetUsersByWalletResponse = {
  results: Record<string, BatchUserByWalletResult>;
};
 
type BatchUserByWalletResult =
  | {
      status: 'ok';
      user_id: string;
      twitter_id: string;
      username: string;
      display_name: string;
      profile_image_url?: string | null;
    }
  | { status: 'notFound' };

results is keyed by wallet address. Each entry is either status: 'ok' with the linked profile or status: 'notFound' when no user is linked to that address.