### Docker Deployment (Bash)
Source: https://context7.com/rjdmacedo/knots/llms.txt
Commands for building and running the Knots application using Docker. It includes instructions for building the Docker image, configuring environment variables via `container.env`, and starting the PostgreSQL and application containers. Assumes Docker and npm are installed.
```bash
# Build the Docker image
npm run build-image
# Configure container environment
cp container.env.example container.env
# Edit container.env with your settings
# Start PostgreSQL and Knots containers
npm run start-container
# Access the application
# http://localhost:3000
# Docker Compose includes:
# - PostgreSQL database with automatic schema migrations
# - Knots web application
# - Volume mounts for persistent data
# - Health checks for monitoring
```
--------------------------------
### Docker Deployment
Source: https://context7.com/rjdmacedo/knots/llms.txt
Instructions for deploying Knots using Docker containers, including building the image, configuring the environment, and starting the services.
```APIDOC
## Docker Deployment
### Description
Deploy Knots using Docker containers.
### Steps:
1. **Build the Docker image:**
```bash
npm run build-image
```
2. **Configure container environment:**
Copy the example environment file and edit it with your settings:
```bash
cp container.env.example container.env
# Edit container.env
```
3. **Start PostgreSQL and Knots containers:**
```bash
npm run start-container
```
### Access the application:
`http://localhost:3000`
### Docker Compose includes:
- PostgreSQL database with automatic schema migrations
- Knots web application
- Volume mounts for persistent data
- Health checks for monitoring
```
--------------------------------
### GET /groups/balances/list
Source: https://context7.com/rjdmacedo/knots/llms.txt
Fetches pre-calculated balance information showing who owes whom in a group.
```APIDOC
## GET /groups/balances/list
### Description
Retrieve calculated balances for all participants in a group, showing net amounts owed or due.
### Method
GET
### Endpoint
/groups/balances/list
### Parameters
#### Query Parameters
- **groupId** (string) - Required - The ID of the group whose balances to calculate.
### Response
#### Success Response (200)
- Returns an object mapping participant IDs to their balance information.
- **paid** (number) - Total amount paid by participant in cents.
- **paidFor** (number) - Total share of expenses for participant in cents.
- **total** (number) - Net balance (positive = owed to participant, negative = owes).
#### Response Example
{
"participant-alice-id": { "paid": 50000, "paidFor": 30000, "total": 20000 },
"participant-bob-id": { "paid": 20000, "paidFor": 35000, "total": -15000 },
"participant-charlie-id": { "paid": 30000, "paidFor": 35000, "total": -5000 }
}
```
--------------------------------
### Environment Configuration (.env file)
Source: https://context7.com/rjdmacedo/knots/llms.txt
Defines essential environment variables for configuring the Knots deployment. This includes database connection strings, default currency, and settings for optional features like document uploads, AI receipt scanning, and category suggestions, with examples for AWS S3 and MinIO.
```bash
# .env file configuration
# Database (Required)
POSTGRES_PRISMA_URL=postgresql://postgres:password@localhost:5432/knots
POSTGRES_URL_NON_POOLING=postgresql://postgres:password@localhost:5432/knots
# Default currency for new groups
NEXT_PUBLIC_DEFAULT_CURRENCY_CODE=USD
# Enable expense document uploads (Optional)
NEXT_PUBLIC_ENABLE_EXPENSE_DOCUMENTS=true
S3_UPLOAD_KEY=AKIAIOSFODNN7EXAMPLE
S3_UPLOAD_SECRET=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
S3_UPLOAD_BUCKET=knots-expense-documents
S3_UPLOAD_REGION=us-east-1
S3_UPLOAD_ENDPOINT=https://s3.us-east-1.amazonaws.com
# Alternative: Use MinIO instead of AWS S3
S3_UPLOAD_ENDPOINT=http://minio:9000
# Enable AI receipt scanning (Optional - requires S3)
NEXT_PUBLIC_ENABLE_RECEIPT_EXTRACT=true
OPENAI_API_KEY=sk-proj-xxxxxxxxxxxxxxxxxxxx
# Enable AI category suggestions (Optional)
NEXT_PUBLIC_ENABLE_CATEGORY_EXTRACT=true
OPENAI_API_KEY=sk-proj-xxxxxxxxxxxxxxxxxxxx
```
--------------------------------
### Calculate Group Balances from Expenses in TypeScript
Source: https://context7.com/rjdmacedo/knots/llms.txt
This example computes participant balances and suggests reimbursements based on a list of group expenses fetched via tRPC. It relies on custom utility functions getBalances and getSuggestedReimbursements, with inputs being expense data and outputs including balance objects (paid, paidFor, total) and reimbursement suggestions minimizing transactions. Limitations include client-side calculation which may be inefficient for large datasets and assumes expenses are already loaded.
```typescript
import { getBalances, getSuggestedReimbursements } from '@/lib/balances'
import { trpc } from '@/trpc/client'
const BalanceCalculationExample = () => {
const { data: expenses } = trpc.groups.expenses.list.useQuery({
groupId: 'group-123'
})
if (!expenses) return
{reimb.from} should pay {reimb.to}: ${(reimb.amount / 100).toFixed(2)}
))}
)
}
```
--------------------------------
### List Group Expenses with Filtering in TypeScript
Source: https://context7.com/rjdmacedo/knots/llms.txt
This example retrieves and renders a table of all group expenses using tRPC, including details like date, title, payer, amount, and split mode, with reimbursement marking. It requires the tRPC client for the groups.expenses.list query, inputs groupId, and outputs an array of expense objects. Limitations include basic rendering without pagination or advanced filtering, and handles optional original currency.
```typescript
import { trpc } from '@/trpc/client'
const ExpenseListExample = () => {
const { data: expenses, isLoading } = trpc.groups.expenses.list.useQuery({
groupId: 'group-123'
})
if (isLoading) return
)
}
```
--------------------------------
### Create Expense with Percentage Split (TypeScript)
Source: https://context7.com/rjdmacedo/knots/llms.txt
This example shows how to create an expense split by custom percentages. It utilizes the `trpc.groups.expenses.create.useMutation` hook and specifies `splitMode: "BY_PERCENTAGE"`. The `shares` field represents percentages multiplied by 100, and the sum of shares must equal 10000 (100%).
```typescript
import { trpc } from '@/trpc/client'
const PercentageSplitExample = () => {
const createExpense = trpc.groups.expenses.create.useMutation()
const handlePercentageExpense = async (groupId: string) => {
await createExpense.mutateAsync({
groupId: groupId,
expenseFormValues: {
title: "Rental Car for Road Trip",
amount: 60000, // $600.00
expenseDate: new Date(),
category: 8, // Transportation
paidBy: "participant-bob-id",
paidFor: [
{ participant: "participant-alice-id", shares: 5000 }, // 50% = $300
{ participant: "participant-bob-id", shares: 3000 }, // 30% = $180
{ participant: "participant-charlie-id", shares: 2000 } // 20% = $120
],
splitMode: "BY_PERCENTAGE", // Shares represent percentages * 100
isReimbursement: false,
saveDefaultSplittingOptions: false,
documents: [],
recurrenceRule: "NONE"
}
})
// Total must equal 10000 (100.00%)
}
return
}
```
--------------------------------
### Create Expense with Multi-Currency Conversion (TypeScript)
Source: https://context7.com/rjdmacedo/knots/llms.txt
This example demonstrates creating an expense in a different currency than the group's default currency, with automatic conversion. It uses the `trpc.groups.expenses.create.useMutation` hook and includes `originalAmount`, `originalCurrency`, and `conversionRate` fields. The expense is stored in the group's currency, but the original details are preserved.
```typescript
import { trpc } from '@/trpc/client'
const MultiCurrencyExpenseExample = () => {
const createExpense = trpc.groups.expenses.create.useMutation()
const handleMultiCurrencyExpense = async (groupId: string) => {
// Group uses USD, but expense was in EUR
await createExpense.mutateAsync({
groupId: groupId, // Group with currency: "$" and currencyCode: "USD"
expenseFormValues: {
title: "Museum Tickets in Paris",
amount: 4591, // $45.91 USD (converted amount in cents)
originalAmount: 4200, // €42.00 EUR (original amount in cents)
originalCurrency: "EUR",
conversionRate: 1.093, // 1 EUR = 1.093 USD
expenseDate: new Date(),
category: 10, // Entertainment
paidBy: "participant-alice-id",
paidFor: [
{ participant: "participant-alice-id", shares: 1 },
{ participant: "participant-bob-id", shares: 1 }
],
splitMode: "EVENLY",
isReimbursement: false,
saveDefaultSplittingOptions: false,
documents: [],
recurrenceRule: "NONE"
}
})
// Expense shown as €42.00, calculated in group's USD currency
}
return
}
```
--------------------------------
### Create Expense with Uneven Split by Amount (TypeScript)
Source: https://context7.com/rjdmacedo/knots/llms.txt
This example demonstrates how to create an expense that is split among participants based on exact amounts. It uses the `trpc.groups.expenses.create.useMutation` hook and requires `groupId` and `expenseFormValues` including `splitMode: "BY_AMOUNT"` and specific `shares` for each participant.
```typescript
import { trpc } from '@/trpc/client'
const UnevenSplitExample = () => {
const createExpense = trpc.groups.expenses.create.useMutation()
const handleUnevenExpense = async (groupId: string) => {
await createExpense.mutateAsync({
groupId: groupId,
expenseFormValues: {
title: "Hotel Room - 3 nights",
amount: 45000, // $450.00 total
expenseDate: new Date(),
category: 6, // Accommodation category
paidBy: "participant-alice-id",
paidFor: [
{ participant: "participant-alice-id", shares: 15000 }, // Alice: $150
{ participant: "participant-bob-id", shares: 20000 }, // Bob: $200
{ participant: "participant-charlie-id", shares: 10000 } // Charlie: $100
],
splitMode: "BY_AMOUNT", // Exact amounts mode
isReimbursement: false,
saveDefaultSplittingOptions: false,
documents: [],
recurrenceRule: "NONE"
}
})
// Alice paid $450 but owes $150, so she's owed $300
// Bob owes $200, Charlie owes $100
}
return
}
```
--------------------------------
### Get Group Activity Feed (TypeScript)
Source: https://context7.com/rjdmacedo/knots/llms.txt
Fetches and displays the activity feed for a specific group using TRPC. It handles different activity types like creating, updating, and deleting expenses, as well as group updates. Requires TRPC client setup and a valid groupId.
```typescript
import { trpc } from '@/trpc/client'
const ActivityFeedExample = () => {
const { data: activities } = trpc.groups.activities.list.useQuery({
groupId: 'group-123'
})
return (
Recent Activity
{activities?.map(activity => {
const timestamp = new Date(activity.time).toLocaleString()
let description = ''
switch (activity.activityType) {
case 'CREATE_EXPENSE':
description = `Created expense: ${activity.expenseId}`
break
case 'UPDATE_EXPENSE':
description = `Updated expense: ${activity.expenseId}`
break
case 'DELETE_EXPENSE':
description = `Deleted expense: ${activity.expenseId}`
break
case 'UPDATE_GROUP':
description = 'Updated group information'
break
}
return (
{description}
{activity.data &&
{activity.data}
}
)
})}
)
}
```
--------------------------------
### GET /groups/expenses/list
Source: https://context7.com/rjdmacedo/knots/llms.txt
Retrieves all expenses for a specified group, including regular expenses and reimbursements.
```APIDOC
## GET /groups/expenses/list
### Description
Fetch all expenses recorded for a specific group, with optional filtering capabilities.
### Method
GET
### Endpoint
/groups/expenses/list
### Parameters
#### Query Parameters
- **groupId** (string) - Required - The ID of the group whose expenses to list.
### Response
#### Success Response (200)
- Returns an array of expense objects with full details including dates, amounts, participants, and reimbursement status.
#### Response Example
[
{
"id": "expense-123",
"groupId": "group-123",
"title": "Dinner at Italian Restaurant",
"amount": 12500,
"expenseDate": "2023-01-10T00:00:00.000Z",
"paidBy": "participant-alice-id",
"paidFor": [
{ "participant": "participant-alice-id", "shares": 5000 },
{ "participant": "participant-bob-id", "shares": 5000 },
{ "participant": "participant-charlie-id", "shares": 2500 }
],
"isReimbursement": false,
"createdAt": "2023-01-10T20:15:30.000Z"
},
{
"id": "expense-456",
"title": "Bob pays Alice back for groceries",
"amount": 7500,
"expenseDate": "2023-01-15T00:00:00.000Z",
"paidBy": "participant-bob-id",
"paidFor": [
{ "participant": "participant-alice-id", "shares": 7500 }
],
"isReimbursement": true,
"createdAt": "2023-01-15T12:34:56.789Z"
}
]
```
--------------------------------
### GET /groups/list
Source: https://context7.com/rjdmacedo/knots/llms.txt
Retrieves a list of all expense groups accessible to the authenticated user. This endpoint is used to display all groups the user is a part of.
```APIDOC
## GET /groups/list
### Description
Retrieve all expense groups accessible to the user.
### Method
GET
### Endpoint
/groups/list
### Parameters
None
### Request Example
(No request body needed for GET request)
### Response
#### Success Response (200)
- **groups** (array) - A list of group objects.
- **id** (string) - The unique identifier for the group.
- **name** (string) - The name of the group.
- **currency** (string) - The currency symbol of the group.
- **participants** (array) - A list of participants in the group.
- **name** (string) - The name of the participant.
- **createdAt** (string) - The date and time the group was created (ISO format).
#### Response Example
```json
[
{
"id": "group-123",
"name": "European Vacation 2025",
"currency": "€",
"participants": [
{ "name": "Alice Johnson" },
{ "name": "Bob Smith" },
{ "name": "Charlie Davis" }
],
"createdAt": "2025-01-10T10:00:00Z"
}
]
```
```
--------------------------------
### Get Group Statistics using TRPC
Source: https://context7.com/rjdmacedo/knots/llms.txt
Fetches and displays spending analytics for a given group using TRPC queries. It shows total spending, breakdown by category, and spending by participant. Includes loading and no-data states. Requires the TRPC client.
```typescript
import { trpc } from '@/trpc/client'
const GroupStatsExample = () => {
const { data: stats, isLoading } = trpc.groups.stats.get.useQuery({
groupId: 'group-123'
})
if (isLoading) return
)
}
```
--------------------------------
### Get Group Activity Feed
Source: https://context7.com/rjdmacedo/knots/llms.txt
Retrieve a feed of all changes and events within a specific group. This endpoint is useful for tracking group activity over time.
```APIDOC
## GET /groups/{groupId}/activities
### Description
Track all changes and events in a group.
### Method
GET
### Endpoint
/groups/{groupId}/activities
### Parameters
#### Path Parameters
- **groupId** (string) - Required - The ID of the group to retrieve activities for.
#### Query Parameters
None
#### Request Body
None
### Request Example
None
### Response
#### Success Response (200)
- **id** (string) - Unique identifier for the activity.
- **groupId** (string) - The ID of the group the activity belongs to.
- **time** (string) - The timestamp of the activity.
- **activityType** (string) - The type of activity (e.g., CREATE_EXPENSE, UPDATE_EXPENSE, DELETE_EXPENSE, UPDATE_GROUP).
- **expenseId** (string) - The ID of the expense related to the activity (if applicable).
- **data** (object) - Additional data associated with the activity (if applicable).
#### Response Example
```json
[
{
"id": "activity-1",
"groupId": "group-123",
"time": "2024-01-01T10:00:00Z",
"activityType": "CREATE_EXPENSE",
"expenseId": "expense-abc",
"data": {}
}
]
```
```
--------------------------------
### Create Reimbursement Expense using tRPC in TypeScript
Source: https://context7.com/rjdmacedo/knots/llms.txt
This snippet demonstrates recording a direct reimbursement payment between group participants using a tRPC mutation. It requires the tRPC client and depends on group and participant IDs. Inputs include expense details like amount, date, and split mode; outputs trigger the creation of a reimbursement expense marked as such, with no return value shown. Limitations include fixed currency handling in cents and no error handling in the example.
```typescript
import { trpc } from '@/trpc/client'
const ReimbursementExample = () => {
const createExpense = trpc.groups.expenses.create.useMutation()
const handleReimbursement = async (groupId: string) => {
await createExpense.mutateAsync({
groupId: groupId,
expenseFormValues: {
title: "Bob pays Alice back for groceries",
amount: 7500, // $75.00
expenseDate: new Date(),
category: 0, // General/Uncategorized
paidBy: "participant-bob-id", // Bob pays
paidFor: [
{ participant: "participant-alice-id", shares: 7500 } // Alice receives
],
splitMode: "BY_AMOUNT",
isReimbursement: true, // Mark as reimbursement
saveDefaultSplittingOptions: false,
documents: [],
recurrenceRule: "NONE"
}
})
// This is a settlement, not a new expense
}
return
}
```
--------------------------------
### Environment Configuration
Source: https://context7.com/rjdmacedo/knots/llms.txt
Configure Knots deployment using environment variables. Covers database, currency, file uploads, and AI features.
```APIDOC
## Environment Configuration
### Description
Configure Knots deployment with environment variables.
### Example `.env` file configuration:
```dotenv
# Database (Required)
POSTGRES_PRISMA_URL=postgresql://postgres:password@localhost:5432/knots
POSTGRES_URL_NON_POOLING=postgresql://postgres:password@localhost:5432/knots
# Default currency for new groups
NEXT_PUBLIC_DEFAULT_CURRENCY_CODE=USD
# Enable expense document uploads (Optional)
NEXT_PUBLIC_ENABLE_EXPENSE_DOCUMENTS=true
S3_UPLOAD_KEY=AKIAIOSFODNN7EXAMPLE
S3_UPLOAD_SECRET=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
S3_UPLOAD_BUCKET=knots-expense-documents
S3_UPLOAD_REGION=us-east-1
S3_UPLOAD_ENDPOINT=https://s3.us-east-1.amazonaws.com
# Alternative: Use MinIO instead of AWS S3
# S3_UPLOAD_ENDPOINT=http://minio:9000
# Enable AI receipt scanning (Optional - requires S3)
NEXT_PUBLIC_ENABLE_RECEIPT_EXTRACT=true
OPENAI_API_KEY=sk-proj-xxxxxxxxxxxxxxxxxxxx
# Enable AI category suggestions (Optional)
NEXT_PUBLIC_ENABLE_CATEGORY_EXTRACT=true
OPENAI_API_KEY=sk-proj-xxxxxxxxxxxxxxxxxxxx
```
```
--------------------------------
### POST /groups/create
Source: https://context7.com/rjdmacedo/knots/llms.txt
Creates a new expense sharing group with specified participants and currency settings. This endpoint is essential for initiating any expense tracking within a new context.
```APIDOC
## POST /groups/create
### Description
Creates a new expense sharing group with participants and currency settings.
### Method
POST
### Endpoint
/groups/create
### Parameters
#### Request Body
- **groupFormValues** (object) - Required - Contains the details for the new group.
- **name** (string) - Required - The name of the group.
- **information** (string) - Optional - Additional details about the group.
- **currency** (string) - Required - The primary currency symbol for the group (e.g., "€").
- **currencyCode** (string) - Required - The ISO currency code (e.g., "EUR").
- **participants** (array) - Required - A list of participants to add to the group.
- **name** (string) - Required - The name of the participant.
### Request Example
```json
{
"groupFormValues": {
"name": "European Vacation 2025",
"information": "Our amazing trip to Spain and France",
"currency": "€",
"currencyCode": "EUR",
"participants": [
{ "name": "Alice Johnson" },
{ "name": "Bob Smith" },
{ "name": "Charlie Davis" }
]
}
}
```
### Response
#### Success Response (200)
- **groupId** (string) - The unique identifier for the newly created group.
#### Response Example
```json
{
"groupId": "new-group-id-123"
}
```
```
--------------------------------
### POST /groups/balances/suggestions
Source: https://context7.com/rjdmacedo/knots/llms.txt
Calculates optimized reimbursement suggestions to settle group balances with minimal transactions.
```APIDOC
## POST /groups/balances/suggestions
### Description
Generate optimized reimbursement suggestions to settle all group balances with the fewest possible transactions.
### Method
POST
### Endpoint
/groups/balances/suggestions
### Parameters
#### Request Body
- **balances** (object) - Required - Current balances from all group participants.
- **[participantId]** (object) - Balance details for each participant.
- **paid** (number) - Total paid by participant in cents.
- **paidFor** (number) - Total share of expenses for participant in cents.
- **total** (number) - Net balance (positive = owed to participant, negative = owes).
### Request Example
{
"balances": {
"participant-alice-id": { "paid": 50000, "paidFor": 30000, "total": 20000 },
"participant-bob-id": { "paid": 20000, "paidFor": 35000, "total": -15000 },
"participant-charlie-id": { "paid": 30000, "paidFor": 35000, "total": -5000 }
}
}
### Response
#### Success Response (200)
- Returns an array of suggested reimbursement transactions.
- **from** (string) - ID of participant who should pay.
- **to** (string) - ID of participant who should receive.
- **amount** (number) - Amount to transfer in cents.
#### Response Example
[
{ "from": "participant-bob-id", "to": "participant-alice-id", "amount": 15000 },
{ "from": "participant-charlie-id", "to": "participant-alice-id", "amount": 5000 }
]
```
--------------------------------
### Application Health Check Endpoints (Bash)
Source: https://context7.com/rjdmacedo/knots/llms.txt
Provides bash commands to check the application's health using curl. It includes endpoints for readiness (checking database connectivity) and liveness (checking if the application is running). Useful for production deployment monitoring.
```bash
# Check if application is ready to serve requests (includes database)
curl https://your-app.com/api/health
# or
curl https://your-app.com/api/health/readiness
# Response on success:
# HTTP 200 OK
# { "status": "healthy", "database": "connected" }
# Response on database failure:
# HTTP 503 Service Unavailable
# { "status": "unhealthy", "database": "disconnected" }
# Check if application is running (no database check)
curl https://your-app.com/api/health/liveness
# Response:
# HTTP 200 OK
# { "status": "alive" }
```
--------------------------------
### List All Groups using tRPC
Source: https://context7.com/rjdmacedo/knots/llms.txt
Shows how to fetch and display a list of all expense groups accessible to the current user using tRPC. It handles loading and error states, displaying group names, currencies, participant counts, and creation dates.
```typescript
import { trpc } from '@/trpc/client'
const GroupListExample = () => {
// Automatically fetches and caches group data
const { data: groups, isLoading, error } = trpc.groups.list.useQuery()
if (isLoading) return
)
}
```
--------------------------------
### Export Expenses to JSON
Source: https://context7.com/rjdmacedo/knots/llms.txt
Download all expenses for a specific group in JSON format, including full expense details.
```APIDOC
## Export Expenses to JSON
### Description
Download group expenses in structured JSON format.
### Method
GET
### Endpoint
/groups/{groupId}/expenses/export/json
### Parameters
#### Path Parameters
- **groupId** (string) - Required - The ID of the group whose expenses are to be exported.
#### Query Parameters
None
#### Request Body
None
### Request Example
```bash
curl https://your-app.com/groups/group-123/expenses/export/json -o expenses.json
```
### Response
#### Success Response (200)
- **File Content** (JSON) - The downloaded file contains full expense details including participants and split information.
#### Response Example (JSON Structure - illustrative)
```json
{
"expenses": [
{
"id": "expense-abc",
"groupId": "group-123",
"description": "Dinner at Restaurant",
"amount": 125.00,
"currency": "USD",
"date": "2025-01-15T00:00:00Z",
"paidBy": "Alice",
"participants": ["Alice", "Bob", "Charlie"],
"splitMode": "EVENLY"
}
]
}
```
```
--------------------------------
### Export Expenses to CSV
Source: https://context7.com/rjdmacedo/knots/llms.txt
Download all expenses for a specific group in CSV format for external analysis.
```APIDOC
## Export Expenses to CSV
### Description
Download group expenses as CSV for external analysis.
### Method
GET
### Endpoint
/groups/{groupId}/expenses/export/csv
### Parameters
#### Path Parameters
- **groupId** (string) - Required - The ID of the group whose expenses are to be exported.
#### Query Parameters
None
#### Request Body
None
### Request Example
```bash
curl https://your-app.com/groups/group-123/expenses/export/csv -o expenses.csv
```
### Response
#### Success Response (200)
- **File Content** (CSV) - The downloaded file contains expense data in CSV format.
#### CSV Format
`Date,Description,Category,Amount,Currency,Paid By,Paid For,Split Mode`
`2025-01-15,"Dinner at Restaurant","Food & Drink",125.00,USD,"Alice","Alice, Bob, Charlie",EVENLY`
```
--------------------------------
### Health Check Endpoints
Source: https://context7.com/rjdmacedo/knots/llms.txt
Monitor the status of the application for production deployments. Includes readiness and liveness checks.
```APIDOC
## Health Check Endpoints
### Description
Monitor application status for production deployments.
### Method
GET
### Endpoint
/api/health
/api/health/readiness
/api/health/liveness
### Parameters
None
### Request Example
```bash
curl https://your-app.com/api/health
```
### Response
#### Success Response (200)
- **status** (string) - The current status of the application (e.g., "healthy", "alive").
- **database** (string) - The connection status of the database (e.g., "connected", "disconnected") for `/api/health` and `/api/health/readiness`.
#### Response Example (Success)
```json
{
"status": "healthy",
"database": "connected"
}
```
#### Response Example (Database Failure)
```json
{
"status": "unhealthy",
"database": "disconnected"
}
```
#### Response Example (Liveness)
```json
{
"status": "alive"
}
```
```
--------------------------------
### Create a Group using tRPC
Source: https://context7.com/rjdmacedo/knots/llms.txt
Demonstrates how to create a new expense sharing group using the tRPC client. It requires group details like name, currency, and participants. The function returns a group ID upon successful creation.
```typescript
import { trpc } from '@/trpc/client'
// Client-side usage in a React component
const CreateGroupExample = () => {
const createGroup = trpc.groups.create.useMutation()
const handleCreateGroup = async () => {
try {
const result = await createGroup.mutateAsync({
groupFormValues: {
name: "European Vacation 2025",
information: "Our amazing trip to Spain and France",
currency: "€",
currencyCode: "EUR",
participants: [
{ name: "Alice Johnson" },
{ name: "Bob Smith" },
{ name: "Charlie Davis" }
]
}
})
console.log(`Group created with ID: ${result.groupId}`)
// Navigate to /groups/${result.groupId}
} catch (error) {
console.error('Failed to create group:', error)
}
}
return
}
```
--------------------------------
### List Expense Categories using TRPC
Source: https://context7.com/rjdmacedo/knots/llms.txt
Retrieves a list of available expense categories using TRPC queries and renders them as options in a select dropdown. Includes an 'Uncategorized' option. Requires the TRPC client.
```typescript
import { trpc } from '@/trpc/client'
const CategoriesExample = () => {
const { data: categories } = trpc.categories.list.useQuery()
return (
)
// Categories include:
// - Food & Drink (Restaurant, Groceries, Bar)
// - Transportation (Car, Bus, Train, etc.)
// - Accommodation (Hotel, Airbnb)
// - Entertainment (Movies, Sports, Music)
// - Shopping
// - Utilities
// - And more...
}
```
--------------------------------
### POST /groups/expenses/create
Source: https://context7.com/rjdmacedo/knots/llms.txt
Creates a new expense or reimbursement record between group participants. Reimbursements are marked with the isReimbursement flag.
```APIDOC
## POST /groups/expenses/create
### Description
Record a direct payment between participants, either as a regular expense or as a reimbursement.
### Method
POST
### Endpoint
/groups/expenses/create
### Parameters
#### Request Body
- **groupId** (string) - Required - The ID of the group where the expense is being recorded.
- **expenseFormValues** (object) - Required - Details of the expense/reimbursement.
- **title** (string) - Required - Description of the expense.
- **amount** (number) - Required - Amount in cents (e.g., 7500 for $75.00).
- **expenseDate** (string) - Required - Date of the expense in ISO format.
- **category** (number) - Required - Expense category identifier.
- **paidBy** (string) - Required - ID of participant who paid.
- **paidFor** (array) - Required - List of participants who benefited from the expense.
- **participant** (string) - Required - ID of participant.
- **shares** (number) - Required - Amount owed by this participant in cents.
- **splitMode** (string) - Required - How the expense is split (e.g., "BY_AMOUNT").
- **isReimbursement** (boolean) - Required - True if this is a reimbursement.
- **saveDefaultSplittingOptions** (boolean) - Required - Whether to save splitting options as defaults.
- **documents** (array) - Required - Any attached documents (empty array if none).
- **recurrenceRule** (string) - Required - Recurrence rule ("NONE" for one-time expenses).
### Request Example
{
"groupId": "group-123",
"expenseFormValues": {
"title": "Bob pays Alice back for groceries",
"amount": 7500,
"expenseDate": "2023-01-15T00:00:00.000Z",
"category": 0,
"paidBy": "participant-bob-id",
"paidFor": [
{ "participant": "participant-alice-id", "shares": 7500 }
],
"splitMode": "BY_AMOUNT",
"isReimbursement": true,
"saveDefaultSplittingOptions": false,
"documents": [],
"recurrenceRule": "NONE"
}
}
### Response
#### Success Response (200)
- Returns the created expense object with all details including generated ID.
#### Response Example
{
"id": "expense-456",
"groupId": "group-123",
"title": "Bob pays Alice back for groceries",
"amount": 7500,
"expenseDate": "2023-01-15T00:00:00.000Z",
"category": 0,
"paidBy": "participant-bob-id",
"paidFor": [
{ "participant": "participant-alice-id", "shares": 7500 }
],
"splitMode": "BY_AMOUNT",
"isReimbursement": true,
"createdAt": "2023-01-15T12:34:56.789Z"
}
```
--------------------------------
### Import Expenses from Splitwise using TRPC
Source: https://context7.com/rjdmacedo/knots/llms.txt
Enables importing expenses from a Splitwise CSV export into Knots using TRPC mutations. It handles file uploads, reads CSV content, and sends it for processing. Requires the TRPC client and a CSV file.
```typescript
import { trpc } from '@/trpc/client'
const SplitwiseImportExample = () => {
const importExpenses = trpc.groups.expenses.importSplitwise.useMutation()
const handleImport = async (groupId: string, csvFile: File) => {
try {
// Read CSV file content
const csvContent = await csvFile.text()
const result = await importExpenses.mutateAsync({
groupId: groupId,
csvContent: csvContent
})
console.log(`Imported ${result.count} expenses from Splitwise`)
} catch (error) {
console.error('Import failed:', error)
}
}
const handleFileUpload = (e: React.ChangeEvent) => {
const file = e.target.files?.[0]
if (file && file.type === 'text/csv') {
handleImport('group-123', file)
}
}
return (
Import from Splitwise
Export your Splitwise data as CSV and upload it here
)
}
```
--------------------------------
### Query Group Balances via tRPC in TypeScript
Source: https://context7.com/rjdmacedo/knots/llms.txt
This snippet fetches pre-calculated balances for a group using a tRPC query, displaying owed/owes amounts for each participant. It depends on the tRPC client for the groups.balances.list endpoint, with input as groupId and output as a balances object with total amounts in cents. Limitations include loading state handling but no error management, and assumes server-side calculation.
```typescript
import { trpc } from '@/trpc/client'
const GroupBalancesExample = () => {
const { data: balances, isLoading } = trpc.groups.balances.list.useQuery({
groupId: 'group-123'
})
if (isLoading) return
)
}
```
--------------------------------
### Export Expenses to JSON (Bash)
Source: https://context7.com/rjdmacedo/knots/llms.txt
Exports all group expenses in a structured JSON format using curl. The output is saved to a file named 'expenses.json'. This format includes full expense details, participant information, and split details.
```bash
# Export all expenses as JSON
curl https://your-app.com/groups/group-123/expenses/export/json \
-o expenses.json
# JSON includes full expense details with participants and split information
```
--------------------------------
### POST /groups/expenses/create
Source: https://context7.com/rjdmacedo/knots/llms.txt
Creates a new expense within a specified group, allowing for various splitting methods. This is the core endpoint for recording shared costs.
```APIDOC
## POST /groups/expenses/create
### Description
Create a new expense with a specified split mode among participants.
### Method
POST
### Endpoint
/groups/expenses/create
### Parameters
#### Request Body
- **groupId** (string) - Required - The ID of the group the expense belongs to.
- **expenseFormValues** (object) - Required - The details of the expense.
- **title** (string) - Required - The title or description of the expense.
- **amount** (number) - Required - The total amount of the expense (in cents).
- **expenseDate** (string) - Required - The date of the expense (ISO format).
- **category** (number) - Required - The ID of the expense category.
- **paidBy** (string) - Required - The ID of the participant who paid for the expense.
- **paidFor** (array) - Required - Details of how the expense is split among participants.
- **participant** (string) - Required - The ID of the participant.
- **shares** (number) - Optional - Number of shares for percentage/evenly splits.
- **percentage** (number) - Optional - Percentage for percentage splits.
- **amount** (number) - Optional - Exact amount for exact amount splits.
- **splitMode** (string) - Required - The mode used for splitting the expense (e.g., "EVENLY", "BY_SHARES", "BY_PERCENTAGE", "BY_EXACT_AMOUNTS").
- **isReimbursement** (boolean) - Required - Whether this is a reimbursement.
- **saveDefaultSplittingOptions** (boolean) - Required - Whether to save this splitting configuration as default.
- **documents** (array) - Optional - List of document IDs associated with the expense.
- **recurrenceRule** (string) - Optional - Rule for recurring expenses (e.g., "NONE").
### Request Example
```json
{
"groupId": "group-123",
"expenseFormValues": {
"title": "Dinner at Italian Restaurant",
"amount": 12500,
"expenseDate": "2025-01-15T00:00:00Z",
"category": 1,
"paidBy": "participant-alice-id",
"paidFor": [
{ "participant": "participant-alice-id", "shares": 1 },
{ "participant": "participant-bob-id", "shares": 1 },
{ "participant": "participant-charlie-id", "shares": 1 }
],
"splitMode": "EVENLY",
"isReimbursement": false,
"saveDefaultSplittingOptions": false,
"documents": [],
"recurrenceRule": "NONE"
}
}
```
### Response
#### Success Response (200)
- **expenseId** (string) - The unique identifier for the newly created expense.
#### Response Example
```json
{
"expenseId": "new-expense-id-456"
}
```
```