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

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, 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 or project.go). Handlers follow the standard http.HandlerFunc signature:

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) 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) 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).
  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), 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 using the Chi router. Routes are grouped by feature and protected by middleware.

Add your endpoint under the appropriate resource group:

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).

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) 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) 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). 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:

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

For faster feedback during development of backend changes only:

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 using Chi router groups with middleware.RequireAuth and middleware.RequireWorkspace.
  • Test using the harness in 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 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).

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).

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) for the setup pattern using a real HTTP server instance against a test database.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →