Skip to content

API Contracts - Server (tRPC)

Part: server Framework: Hono + tRPC 11 Generated: 2026-01-04

The server exposes a type-safe tRPC API consumed by the client and subscription apps. All procedures require authentication via Better Auth or WorkOS session.

appRouter
├── getAccounts # Query: Get user's WhatsApp accounts
├── account # Account management router
│ ├── addAccount # Mutation: Create new WhatsApp account
│ └── deleteAccount # Mutation: Delete account (cascades)
├── chat # Chat operations router
│ ├── getTags # Query: Get tags for accounts
│ ├── getTag # Query: Get single tag
│ └── setTag # Mutation: Create/update tag
├── folders # Folder management router
│ ├── getFolders # Query: Get folders for accounts
│ ├── createFolder # Mutation: Create folder
│ ├── updateFolder # Mutation: Update folder
│ ├── deleteFolder # Mutation: Delete folder
│ ├── createChatFolder # Mutation: Assign chat to folder
│ └── deleteChatFolder # Mutation: Remove chat from folder
├── priorities # Priority management router
├── subscriptions # Subscription management router
│ ├── getUserSubscription # Query: Get current subscription
│ ├── verifyPayment # Mutation: Verify Creem payment
│ ├── cancelSubscription # Mutation: Cancel subscription
│ ├── getBillingHistory # Query: Get billing history
│ └── devGrantSubscription # Mutation: Dev-only subscription grant
└── templates # Template management router
├── getTemplates # Query: Get templates for account
├── getTemplate # Query: Get single template
├── createTemplate # Mutation: Create template (limit enforced)
├── updateTemplate # Mutation: Update template
└── deleteTemplate # Mutation: Delete template
  • Type: Query
  • Auth: Required (session.user.id)
  • Returns: Array of account objects with computed accountNumber
  • Type: Mutation
  • Auth: Required + subscription limit check
  • Input:
    {
    id?: string // Optional UUID for coordination
    name: string
    phoneNumber: string
    avatar?: string
    color: string
    status?: 'active' | 'away' | 'offline'
    isBusinessAccount: boolean
    isVerified: boolean
    accountNumber: number
    }
  • Errors: FORBIDDEN (account limit), UNAUTHORIZED
  • Type: Mutation
  • Auth: Required + ownership check
  • Input: { id: string }
  • Cascade Deletes: chat_tags, folders, templates, chat_priorities, chat_folders
  • Type: Query
  • Input: { accountIds: string[] }
  • Type: Mutation
  • Input: { chatId: string, accountId: string, tag: string }
  • Behavior: Upsert (update existing or create new)
  • Type: Query
  • Input: { accountIds: string[] }
  • Returns: Folders with nested chats and account.accountNumber
  • Type: Mutation
  • Input: { name: string, color: string, accountId: string }
  • Type: Mutation
  • Auth: Required
  • Input:
    {
    request_id: string | null
    checkout_id: string
    order_id?: string
    customer_id?: string
    subscription_id?: string
    product_id?: string
    signature: string
    planType: 'pro_monthly' | 'pro_yearly'
    }
  • Behavior:
    1. Check for duplicate checkout_id
    2. Verify Creem signature (SHA256)
    3. Create subscription record
  • Idempotent: Returns existing subscription if already processed
  • Type: Mutation
  • Behavior:
    1. Find active subscription for user
    2. Cancel with Creem API
    3. Update local status to ‘canceled’
  • Type: Mutation
  • Input: { name: string, content: string, accountId: string }
  • Limits: Free accounts limited to FREE_TEMPLATE_LIMIT templates per account
  • Middleware: subscriptionLimits checks canCreateTemplate
interface TRPCContext {
session: {
user?: {
id: string
}
} | null
user: {
id: string
subscription: Subscription | null
} | null
}

Injected on account and template mutations. Provides:

  • ctx.canAddAccount: boolean
  • ctx.canCreateTemplate: Record<accountId, boolean>
CodeMeaning
UNAUTHORIZEDNo valid session
FORBIDDENSubscription limit reached
NOT_FOUNDResource doesn’t exist or no permission
BAD_REQUESTInvalid signature or payment verification failed
CONFLICTDatabase constraint violation
INTERNAL_SERVER_ERRORUnexpected error