# TaxHacker API: Complete REST Reference for Next.js App Router

> Explore the TaxHacker API REST reference for Next.js App Router. Access endpoints for currency conversion, Stripe billing, progress streams, and authentication.

- Repository: [Vasily Zubarev/TaxHacker](https://github.com/vas3k/TaxHacker)
- Tags: api-reference
- Published: 2026-04-01

---

**The TaxHacker API is a REST-style JSON API built with Next.js 13 App Router, exposing protected endpoints for currency conversion, Stripe billing, real-time progress streams, and authentication via better-auth.**

The TaxHacker API powers the personal finance automation features in the [vas3k/TaxHacker](https://github.com/vas3k/TaxHacker) repository. It follows standard REST conventions with TypeScript implementations living in the `app/api` directory, utilizing Next.js server handlers and JWT-based session management.

## Core Architecture

The API architecture separates concerns across authentication, business logic, and data persistence layers.

### Authentication and Sessions

All protected routes rely on **better-auth** for JWT session management. The `auth` object is configured in [`lib/auth.ts`](https://github.com/vas3k/TaxHacker/blob/main/lib/auth.ts) and exposed through a catch-all route at `app/api/auth/[...all]/route.ts` that delegates to `toNextJsHandler`. The `getSession()` helper function, defined in [`lib/auth.ts`](https://github.com/vas3k/TaxHacker/blob/main/lib/auth.ts) (lines 67-75), validates the current user and returns either the session object or `null`, enforcing security at the edge.

### Routing Conventions

Following Next.js 13 App Router patterns, each API endpoint exports standard `GET`, `POST`, or other HTTP methods from files inside `app/api/`. The file path automatically maps to the URL route. For example, [`app/api/currency/route.ts`](https://github.com/vas3k/TaxHacker/blob/main/app/api/currency/route.ts) handles requests to `/api/currency`.

### Data and Payment Layers

Business logic resides in the `models/` directory, which contains Prisma-backed TypeScript modules for users, transactions, and progress tracking. Stripe integration is centralized in [`lib/stripe.ts`](https://github.com/vas3k/TaxHacker/blob/main/lib/stripe.ts), handling checkout sessions, billing portal generation, and webhook verification.

## Available Endpoints

The TaxHacker API exposes several functional groups for financial operations and background processing.

### Authentication Endpoints

All user authentication flows—including sign-in, sign-up, password reset, and token refresh—route through `/api/auth/*`. These endpoints are generated dynamically by better-auth and do not require manual session validation, as the library handles JWT verification internally.

### Currency Conversion

`GET /api/currency?from=USD&to=EUR&date=2023-09-01`

Returns historic exchange rates for tax reporting dates. This endpoint implements a simple in-memory **PoorManCache** that stores rates for 24 hours to reduce external API calls. Requests must include authentication cookies to access this protected resource.

### Real-Time Progress Streaming

`GET /api/progress/[progressId]`

Provides Server-Sent Events (SSE) for long-running background jobs such as transaction imports. The handler in `app/api/progress/[progressId]/route.ts` polls the database at intervals and pushes JSON updates to the client stream, requiring a valid session to prevent unauthorized job status leakage.

### Stripe Integration

The billing system exposes three primary routes:

- **`POST /api/stripe/checkout?code=pro`** – Creates a Stripe Checkout Session for subscription plans. Protected by session validation.
- **`GET /api/stripe/portal`** – Generates a customer portal session for managing existing subscriptions. Returns a redirect URL.
- **`POST /api/stripe/webhook`** – Receives asynchronous events from Stripe (checkout completion, subscription updates). Public endpoint secured via Stripe signature verification rather than session cookies.

## Implementation Examples

### Fetching Exchange Rates

To retrieve cached currency rates, include credentials to pass the JWT cookie:

```typescript
async function getRate() {
  const res = await fetch(
    '/api/currency?from=USD&to=EUR&date=2023-09-01',
    { credentials: 'include' }               // sends the auth cookie / JWT
  )
  const data = await res.json()
  if (!res.ok) throw new Error(data.error)
  console.log('Rate:', data.rate, 'cached:', data.cached)
}

```

Implementation located in: [`app/api/currency/route.ts`](https://github.com/vas3k/TaxHacker/blob/main/app/api/currency/route.ts)

### Initiating Stripe Checkout

Create a billing session and redirect the user:

```typescript
async function startCheckout(planCode: string) {
  const res = await fetch(`/api/stripe/checkout?code=${planCode}`, {
    method: 'POST',
    credentials: 'include',
  })
  const { session, error } = await res.json()
  if (error) throw new Error(error)

  // Redirect the user to Stripe
  window.location.href = session.url
}

```

Implementation located in: [`app/api/stripe/checkout/route.ts`](https://github.com/vas3k/TaxHacker/blob/main/app/api/stripe/checkout/route.ts)

### Listening to Progress Streams

Connect to the SSE endpoint for real-time job updates:

```typescript
function listenProgress(id: string) {
  const evtSource = new EventSource(`/api/progress/${id}?type=import`)

  evtSource.onmessage = (e) => {
    const progress = JSON.parse(e.data)
    console.log('Progress:', progress)
  }

  evtSource.onerror = () => {
    console.error('Stream error')
    evtSource.close()
  }
}

```

Implementation located in: `app/api/progress/[progressId]/route.ts`

### Authenticating Users

Sign in using the better-auth endpoints:

```typescript
async function signIn(email: string, password: string) {
  const res = await fetch('/api/auth/sign-in', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ email, password })
  })
  const result = await res.json()
  if (!res.ok) throw new Error(result.error)
  // Session cookie/JWT is now stored automatically
}

```

Implementation located in: `app/api/auth/[...all]/route.ts`

## Key Source Files

Understanding the TaxHacker API requires familiarity with these specific modules:

- **`app/api/auth/[...all]/route.ts`** – Wildcard route delegating all authentication to better-auth handlers
- **`app/api/progress/[progressId]/route.ts`** – SSE stream implementation for background job monitoring
- **[`app/api/currency/route.ts`](https://github.com/vas3k/TaxHacker/blob/main/app/api/currency/route.ts)** – Exchange rate endpoint with 24-hour caching logic
- **[`app/api/stripe/webhook/route.ts`](https://github.com/vas3k/TaxHacker/blob/main/app/api/stripe/webhook/route.ts)** – Stripe event receiver with signature verification
- **[`app/api/stripe/checkout/route.ts`](https://github.com/vas3k/TaxHacker/blob/main/app/api/stripe/checkout/route.ts)** – Checkout session creation handler
- **[`app/api/stripe/portal/route.ts`](https://github.com/vas3k/TaxHacker/blob/main/app/api/stripe/portal/route.ts)** – Billing portal session generator
- **[`lib/auth.ts`](https://github.com/vas3k/TaxHacker/blob/main/lib/auth.ts)** – better-auth configuration, JWT settings, and `getSession()` helper
- **[`lib/stripe.ts`](https://github.com/vas3k/TaxHacker/blob/main/lib/stripe.ts)** – Stripe client initialization and plan configuration
- **`models/`** – Prisma models for transactions, users, and progress data

## Summary

- The TaxHacker API is a **REST-style JSON API** built on Next.js 13 App Router conventions
- Authentication uses **better-auth** with JWT sessions validated via [`lib/auth.ts`](https://github.com/vas3k/TaxHacker/blob/main/lib/auth.ts)
- Protected endpoints require session cookies, while Stripe webhooks use signature verification
- **Currency rates** are cached for 24 hours using `PoorManCache` in the currency route
- **Real-time progress** is delivered via Server-Sent Events from `/api/progress/[progressId]`
- **Stripe integration** supports checkout sessions, billing portals, and webhook processing
- All business logic is type-safe TypeScript using Prisma models in the `models/` directory

## Frequently Asked Questions

### What authentication method does the TaxHacker API use?

The API uses **better-auth** with JWT-based sessions. The `getSession()` helper in [`lib/auth.ts`](https://github.com/vas3k/TaxHacker/blob/main/lib/auth.ts) validates tokens on protected routes, while public authentication flows like sign-in and password reset are handled by the catch-all route at `app/api/auth/[...all]/route.ts`.

### How does the TaxHacker API handle real-time progress updates?

Long-running operations stream status updates via **Server-Sent Events (SSE)** from the `/api/progress/[progressId]` endpoint. The server polls the database and pushes JSON payloads to connected clients, automatically closing the stream when the job completes or encounters an error.

### Is the TaxHacker API publicly accessible?

Most endpoints require authentication via session cookies. However, the Stripe webhook endpoint at `/api/stripe/webhook` is public to receive external events, secured instead by Stripe's signature verification. All other business logic endpoints enforce session validation through the `getSession()` helper.

### Where is the API documentation and source code located?

The complete source code is available in the [vas3k/TaxHacker](https://github.com/vas3k/TaxHacker) repository. Endpoint implementations reside in `app/api/`, shared utilities in `lib/`, and data models in `models/`, all written in TypeScript for type-safe development.