# How to Add a New REST API Endpoint to the Multica Go Backend

> Learn how to add a new REST API endpoint to the Multica Go backend. This guide covers handler creation, router registration, service layer logic, and database code generation for seamless integration.

- Repository: [multica-ai/multica](https://github.com/multica-ai/multica)
- Tags: how-to-guide
- Published: 2026-04-11

---

**To add a new REST API endpoint to the Multica Go backend, create a handler function in `server/internal/handler/`, register it in the Chi router at [`server/cmd/server/router.go`](https://github.com/multica-ai/multica/blob/main/server/cmd/server/router.go), implement business logic in the service layer, and generate type-safe database code using sqlc.**

The multica-ai/multica repository follows a clean architecture pattern that separates HTTP handling, business logic, and data persistence. Whether you are exposing a new resource or adding custom functionality, this guide covers the exact file locations, function signatures, and verification steps used by the core maintainers.

## Create the Handler Function

New HTTP handlers live in the `server/internal/handler/` directory according to the resource they manage.

### Handler Location and Signature

Create a new Go file named after your resource (e.g., [`issue.go`](https://github.com/multica-ai/multica/blob/main/issue.go) or [`project.go`](https://github.com/multica-ai/multica/blob/main/project.go)). Handlers follow the standard `http.HandlerFunc` signature:

```go
func CreateIssue(w http.ResponseWriter, r *http.Request) {
    ctx := r.Context()
    userID := auth.UserIDFromContext(ctx)            // from JWT middleware
    workspaceID := auth.WorkspaceIDFromContext(ctx)  // from X-Workspace-ID header
    
    // Decode request body
    var req CreateIssueRequest
    if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
        api.WriteError(w, err, http.StatusBadRequest)
        return
    }
    
    // Call service layer logic here...
    
    api.WriteJSON(w, http.StatusOK, response)
}

```

Use `json.NewDecoder(r.Body)` to parse incoming JSON and `api.WriteJSON` to serialize responses. For error responses, call `api.WriteError(w, err, status)` to maintain consistency across the API.

### Reference Implementation

See the existing Issue handler at [[`server/internal/handler/issue.go`](https://github.com/multica-ai/multica/blob/main/server/internal/handler/issue.go)](https://github.com/multica-ai/multica/blob/main/server/internal/handler/issue.go) for a complete example that demonstrates request validation, authentication context extraction, and response formatting.

## Implement Business Logic and Database Access

If your endpoint persists data, you must update both the service layer and database queries.

### Service Layer

Core business logic resides in `server/internal/service/`. Add a method to the appropriate service struct (e.g., `IssueService.Create`) that orchestrates database calls and triggers side effects like notifications or real-time events. The service layer abstracts the handler from direct database access and transaction management.

Reference the task service implementation at [[`server/internal/service/task.go`](https://github.com/multica-ai/multica/blob/main/server/internal/service/task.go)](https://github.com/multica-ai/multica/blob/main/server/internal/service/task.go) to see how business logic is organized.

### SQL Queries with sqlc

The Multica backend uses **sqlc** to generate type-safe Go code from SQL. To add database support:

1. Add your SQL query to a file in `server/pkg/db/queries/` (e.g., [`issue.sql`](https://github.com/multica-ai/multica/blob/main/issue.sql)).
2. Run `make sqlc` to regenerate the typed Go code in `server/pkg/db/generated/`.

The generated code provides strongly typed methods for executing queries. You can see the pattern in [[`server/pkg/db/generated/issue.sql.go`](https://github.com/multica-ai/multica/blob/main/server/pkg/db/generated/issue.sql.go)](https://github.com/multica-ai/multica/blob/main/server/pkg/db/generated/issue.sql.go), which contains the generated types and query methods used by the service layer.

## Register the Route in the Router

All HTTP routes are registered in [`server/cmd/server/router.go`](https://github.com/multica-ai/multica/blob/main/server/cmd/server/router.go) using the **Chi** router. Routes are grouped by feature and protected by middleware.

Add your endpoint under the appropriate resource group:

```go
r.Group(func(r chi.Router) {
    r.Use(middleware.RequireAuth)       // JWT verification
    r.Use(middleware.RequireWorkspace)  // X-Workspace-ID validation

    r.Route("/issues", func(r chi.Router) {
        r.Post("/", handler.CreateIssue)   // ← Your new endpoint here
        r.Get("/", handler.ListIssues)
    })
})

```

If your endpoint represents a completely new resource, create a new `r.Route` block. The router setup is defined in [[`server/cmd/server/router.go`](https://github.com/multica-ai/multica/blob/main/server/cmd/server/router.go)](https://github.com/multica-ai/multica/blob/main/server/cmd/server/router.go).

## Apply Middleware for Security

Most endpoints require two standard middleware functions available in `server/internal/middleware/`:

- **`middleware.RequireAuth`** — Verifies the JWT token and populates the context with `userID`.
- **`middleware.RequireWorkspace`** — Validates the `X-Workspace-ID` header and injects the workspace ID into the context.

If your endpoint requires special permissions (e.g., admin-only access), create a custom middleware in `server/internal/middleware/` and append it to the route group's `Use` chain.

## Write Unit and Integration Tests

Testing ensures your endpoint handles authentication, validation, and database interactions correctly.

### Unit Tests

Place unit tests in the handler directory using the `*_test.go` naming convention. The repository provides a test harness in [[`server/internal/handler/handler_test.go`](https://github.com/multica-ai/multica/blob/main/server/internal/handler/handler_test.go)](https://github.com/multica-ai/multica/blob/main/server/internal/handler/handler_test.go) that sets up an in-memory database and authenticated request context.

See [[`server/internal/handler/issue_test.go`](https://github.com/multica-ai/multica/blob/main/server/internal/handler/issue_test.go)](https://github.com/multica-ai/multica/blob/main/server/internal/handler/issue_test.go) for examples of testing authenticated handlers with various input payloads.

### Integration Tests

For end-to-end verification, add tests in `server/cmd/server/` following the pattern established in [[`server/cmd/server/comment_trigger_integration_test.go`](https://github.com/multica-ai/multica/blob/main/server/cmd/server/comment_trigger_integration_test.go)](https://github.com/multica-ai/multica/blob/main/server/cmd/server/comment_trigger_integration_test.go). These tests spin up the full HTTP server and verify request routing, middleware execution, and database state.

## Verify with the Test Pipeline

Before submitting changes, run the verification pipeline to ensure type safety and test coverage:

```bash
make check   # Runs type-checks, unit tests, go tests, and e2e tests

```

For faster feedback during development of backend changes only:

```bash
make test              # Go unit tests only

go test ./... -run <YourTestName>

```

## Summary

Adding REST endpoints to the Multica Go backend involves coordinated changes across handler, service, and database layers:

- **Create** handler functions in `server/internal/handler/` using the standard `http.ResponseWriter` and `*http.Request` signature with `auth.UserIDFromContext` and `auth.WorkspaceIDFromContext` for security context.
- **Implement** business logic in `server/internal/service/` and add SQL queries to `server/pkg/db/queries/` followed by running `make sqlc`.
- **Register** routes in [`server/cmd/server/router.go`](https://github.com/multica-ai/multica/blob/main/server/cmd/server/router.go) using Chi router groups with `middleware.RequireAuth` and `middleware.RequireWorkspace`.
- **Test** using the harness in [`server/internal/handler/handler_test.go`](https://github.com/multica-ai/multica/blob/main/server/internal/handler/handler_test.go) for unit tests and `server/cmd/server/` for integration tests.
- **Verify** with `make check` before deployment.

## Frequently Asked Questions

### What is the standard file location for new HTTP handlers?

New handler files belong in `server/internal/handler/` and should be named after the resource they manage (e.g., [`issue.go`](https://github.com/multica-ai/multica/blob/main/issue.go) for issue-related endpoints). Each file exports handler functions that accept `http.ResponseWriter` and `*http.Request` as parameters, following the pattern established in [[`server/internal/handler/issue.go`](https://github.com/multica-ai/multica/blob/main/server/internal/handler/issue.go)](https://github.com/multica-ai/multica/blob/main/server/internal/handler/issue.go).

### How do I extract user and workspace information from requests?

The authentication middleware populates the request context with user and workspace IDs. Access them using `auth.UserIDFromContext(ctx)` and `auth.WorkspaceIDFromContext(ctx)` after casting `r.Context()` to a local variable. These values are injected by `middleware.RequireAuth` and `middleware.RequireWorkspace` respectively, which must be applied to the route group in the router configuration.

### Why does the Multica backend use sqlc for database access?

The project uses **sqlc** to generate type-safe Go code from SQL files located in `server/pkg/db/queries/`. After writing raw SQL queries in `.sql` files, running `make sqlc` generates Go structs and query methods in `server/pkg/db/generated/`. This approach eliminates boilerplate code, prevents runtime SQL errors through compile-time type checking, and keeps the database layer synchronized with the schema as shown in [[`server/pkg/db/generated/issue.sql.go`](https://github.com/multica-ai/multica/blob/main/server/pkg/db/generated/issue.sql.go)](https://github.com/multica-ai/multica/blob/main/server/pkg/db/generated/issue.sql.go).

### Where should I add integration tests for a new endpoint?

Integration tests reside in `server/cmd/server/` and follow the naming pattern `*_integration_test.go`. These tests verify the complete request lifecycle from HTTP routing through middleware to database persistence. Reference [[`server/cmd/server/comment_trigger_integration_test.go`](https://github.com/multica-ai/multica/blob/main/server/cmd/server/comment_trigger_integration_test.go)](https://github.com/multica-ai/multica/blob/main/server/cmd/server/comment_trigger_integration_test.go) for the setup pattern using a real HTTP server instance against a test database.