Skip to main content

Overview

Categories help you organize and understand your financial activity. Your Finance App supports hierarchical categories with parent-child relationships, allowing you to create detailed breakdowns while maintaining high-level summaries.

Hierarchical Structure

Create parent categories with subcategories for detailed organization

Custom Icons & Colors

Personalize categories with hex colors and icon names for visual clarity

Fixed Expenses

Mark categories as fixed to track recurring monthly obligations

Flexible Types

Categories can be INCOME, EXPENSE, or BOTH for maximum flexibility

Category Types

Each category has a type that determines which transactions can use it:
  • INCOME: Only for income transactions (e.g., Salary, Freelance, Gifts)
  • EXPENSE: Only for expense transactions (e.g., Food, Rent, Transportation)
  • BOTH: Can be used for both income and expenses (e.g., Reimbursements)

Default Categories

When you create an account, the system can seed default categories for you:
POST /categories/seed
This creates a comprehensive category hierarchy including: Expense Categories:
  • Vivienda (Housing): Alquiler, Servicios, Mantenimiento
  • Alimentos (Food): Supermercado, Restaurantes, Delivery
  • Transporte (Transportation): Combustible, Transporte Público, Mantenimiento
  • Salud (Health): Medicamentos, Consultas, Gimnasio
  • And many more…
Income Categories:
  • Salario (Salary)
  • Freelance
  • Inversiones (Investments)
  • Otros Ingresos (Other Income)
Default categories are marked as isFixed: false and can be edited or deleted. Only create the seed once per user.

Creating Custom Categories

Create a new category with POST /categories:
{
  "name": "Entertainment",
  "type": "EXPENSE",
  "color": "#FF5733",
  "icon": "popcorn",
  "isFixed": false
}

Request Parameters

name
string
required
Category name (2-50 characters, must be unique per user)
type
enum
required
Category type: INCOME, EXPENSE, or BOTH
color
string
Hex color code (e.g., #FF5733) for visual identification
icon
string
Icon name (max 50 characters)
isFixed
boolean
Whether this represents a fixed monthly expense (default: false)
parentId
string
UUID of parent category to create a subcategory

Hierarchical Organization

Create subcategories by setting a parentId:
// 1. Create parent category
POST /categories
{
  "name": "Transportation",
  "type": "EXPENSE",
  "color": "#3B82F6",
  "icon": "car"
}
// Response: { "id": "parent-uuid", ... }

// 2. Create subcategory
POST /categories
{
  "name": "Gas",
  "type": "EXPENSE",
  "color": "#3B82F6",
  "icon": "gas-pump",
  "parentId": "parent-uuid"
}
Nesting Limit: The system currently supports 2 levels (parent + child). You cannot create a subcategory of a subcategory.

Hierarchy Rules

When creating a subcategory:
  • The parent must exist and belong to you
  • The parent cannot itself be a subcategory
  • This prevents overly complex hierarchies
When deleting a parent category:
  • All child categories are also soft-deleted
  • Transactions keep their category references
  • The operation is atomic (all or nothing)

Listing Categories

Retrieve all categories with optional filtering:
GET /categories?page=1&limit=20&type=EXPENSE

Query Parameters

  • page (number): Page number (default: 1)
  • limit (number): Results per page (default: 20)
  • type (enum): Filter by INCOME, EXPENSE, or BOTH

Response Format

{
  "data": [
    {
      "id": "uuid",
      "name": "Transportation",
      "type": "EXPENSE",
      "color": "#3B82F6",
      "icon": "car",
      "isFixed": false,
      "parentId": null,
      "userId": "user-uuid",
      "createdAt": "2026-03-01T10:00:00.000Z",
      "updatedAt": "2026-03-01T10:00:00.000Z",
      "deletedAt": null
    },
    {
      "id": "child-uuid",
      "name": "Gas",
      "type": "EXPENSE",
      "color": "#3B82F6",
      "icon": "gas-pump",
      "isFixed": false,
      "parentId": "uuid",
      "userId": "user-uuid",
      "createdAt": "2026-03-01T10:05:00.000Z",
      "updatedAt": "2026-03-01T10:05:00.000Z",
      "deletedAt": null
    }
  ],
  "meta": {
    "total": 45,
    "page": 1,
    "limit": 20,
    "totalPages": 3
  }
}
Categories are returned as a flat list. Use the parentId field to build the hierarchy on the client side.

Getting a Single Category

Retrieve a category with its relationships:
GET /categories/:id
Response includes:
  • The category itself
  • children: Array of subcategories
  • parent: Parent category object (if this is a subcategory)
{
  "id": "uuid",
  "name": "Transportation",
  "type": "EXPENSE",
  "color": "#3B82F6",
  "icon": "car",
  "isFixed": false,
  "parentId": null,
  "children": [
    {
      "id": "child-uuid",
      "name": "Gas",
      "type": "EXPENSE",
      "parentId": "uuid"
    }
  ],
  "parent": null
}

Updating Categories

Update an existing category with PATCH /categories/:id:
{
  "name": "Transport",
  "color": "#2563EB",
  "isFixed": true
}

Validation Rules

  • Name uniqueness: If changing the name, it must not conflict with another category
  • Parent changes: If changing parentId, all parent validation rules apply
  • No self-reference: A category cannot be its own parent

Fixed Expenses

Mark categories as fixed to identify recurring monthly obligations:
{
  "name": "Rent",
  "type": "EXPENSE",
  "isFixed": true
}
Fixed categories help you:
  • Distinguish between fixed and variable expenses in reports
  • Plan your monthly budget more accurately
  • Identify opportunities to reduce recurring costs

Category-Transaction Coherence

The system enforces type coherence between categories and transactions:
  • INCOME transaction → INCOME or BOTH category ✅
  • EXPENSE transaction → EXPENSE or BOTH category ✅
  • INCOME transaction → EXPENSE category ❌
  • EXPENSE transaction → INCOME category ❌
Attempting an invalid combination returns:
{
  "statusCode": 400,
  "message": "No puedes crear una transacción de tipo EXPENSE con una categoría de tipo INCOME"
}

Soft Delete

Deleting a category soft-deletes it and all its children:
DELETE /categories/:id
Response:
{
  "message": "Category deleted successfully",
  "childrenDeleted": 3
}
Soft-deleted categories:
  • Won’t appear in category lists
  • Can still be referenced by existing transactions
  • Preserve data integrity in your financial history

Best Practices

Use the /categories/seed endpoint to get started quickly. You can always customize later.
Limit to 2 levels (parent + child). Deep hierarchies make reports harder to understand.
Group related categories with similar colors (e.g., all food categories in shades of green).
Only use isFixed: true for expenses that recur monthly at the same amount (rent, subscriptions).
15-25 categories is usually enough. Too many categories make budgeting complex.

Common Workflows

Setting Up Your Categories

# 1. Seed default categories
POST /categories/seed

# 2. Add custom categories for your needs
POST /categories
{
  "name": "Side Projects",
  "type": "INCOME",
  "color": "#10B981",
  "icon": "code"
}

# 3. Create subcategories for detail
POST /categories
{
  "name": "Consulting",
  "type": "INCOME",
  "parentId": "side-projects-uuid",
  "color": "#10B981"
}

Reorganizing Categories

# Change a subcategory's parent
PATCH /categories/:id
{
  "parentId": "new-parent-uuid"
}

# Convert to top-level category
PATCH /categories/:id
{
  "parentId": null
}

Build docs developers (and LLMs) love