> ## Documentation Index
> Fetch the complete documentation index at: https://docs.go-mizu.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Registration

> Learn how to register services with Contract and understand all available options

## What is Registration?

Registration is the process of telling Contract about your service. Think of it like introducing your service to Contract: "Here's my interface (what I can do) and my implementation (how I do it). Please make me available to clients."

When you register a service, Contract does several things behind the scenes:

1. **Inspects your interface** - Uses Go's reflection to discover all methods in your interface
2. **Extracts type information** - Finds all input and output types for each method
3. **Generates schemas** - Creates JSON schemas from your Go types (used for validation and documentation)
4. **Creates invokers** - Builds efficient callable wrappers for your methods
5. **Prepares HTTP bindings** - Determines HTTP methods and paths for each operation

After registration, you have a `*RegisteredService` that can be mounted on any transport (REST, JSON-RPC, MCP, etc.).

## Basic Registration

The simplest registration takes your implementation and interface:

```go theme={null}
package main

import (
    "context"

    contract "github.com/go-mizu/mizu/contract/v2"
    "yourapp/todo"  // Your todo package
)

func main() {
    // Create your service implementation
    impl := todo.NewService()

    // Register - the generic parameter [todo.API] specifies which interface to use
    // Contract analyzes todo.API to discover all methods and their types
    svc := contract.Register[todo.API](impl)

    // svc is now a *RegisteredService ready to be mounted on transports
}
```

The generic parameter `[todo.API]` is crucial - it tells Contract which interface defines your API. Your implementation must satisfy this interface, which Go's compiler verifies at compile time.

## Why the Generic Parameter?

You might wonder why we explicitly specify the interface instead of just passing the implementation. There are good reasons:

```go theme={null}
package todo

// The interface defines what's exposed as API
type API interface {
    Create(ctx context.Context, in *CreateInput) (*Todo, error)
    List(ctx context.Context) (*ListOutput, error)
}

// The implementation may have additional methods
type Service struct {
    db *sql.DB
}

// These methods ARE part of the API (defined in the interface)
func (s *Service) Create(ctx context.Context, in *CreateInput) (*Todo, error) { ... }
func (s *Service) List(ctx context.Context) (*ListOutput, error) { ... }

// These methods are NOT part of the API (not in the interface)
// They won't be exposed as endpoints - they're internal helpers
func (s *Service) validateTitle(title string) error { ... }
func (s *Service) generateID() string { ... }
func (s *Service) logOperation(ctx context.Context, op string) { ... }
```

```go theme={null}
// In main.go
svc := contract.Register[todo.API](impl)
// Only Create and List become API endpoints
// validateTitle, generateID, logOperation remain internal
```

This separation between "what's public" (interface) and "what's internal" (implementation) is a fundamental benefit of the interface-first approach.

## Registration Options

Options let you customize how your service is registered. Pass them as additional arguments after the implementation:

```go theme={null}
svc := contract.Register[todo.API](impl,
    contract.WithName("Todo"),
    contract.WithDescription("Todo management API for task tracking"),
    contract.WithDefaultResource("todos"),
)
```

Let's explore each option in detail.

### WithName

Sets the service name. This name appears in documentation and is used for method namespacing:

```go theme={null}
svc := contract.Register[todo.API](impl,
    contract.WithName("Todo"),  // Service name is "Todo"
)
```

**Default**: If not specified, Contract uses the interface name (e.g., "API" from `todo.API`).

**Where the name appears**:

* **OpenAPI specification**: The `info.title` field
* **JSON-RPC**: Method prefix (e.g., `Todo.Create` or `todos.create` depending on resource)
* **MCP**: Tool group name shown to AI assistants

**Example**:

```go theme={null}
// Without WithName - uses interface name "API"
svc := contract.Register[todo.API](impl)
// JSON-RPC method: API.create

// With WithName - uses custom name
svc := contract.Register[todo.API](impl,
    contract.WithName("TodoService"),
)
// JSON-RPC method: TodoService.create
```

### WithDescription

Adds a human-readable description to your service. This helps users understand what your API does:

```go theme={null}
svc := contract.Register[todo.API](impl,
    contract.WithDescription("A todo list API for managing tasks. Supports creating, listing, updating, and deleting todo items."),
)
```

**Where the description appears**:

* **OpenAPI specification**: The `info.description` field
* **MCP**: Server description shown to AI assistants before they use your tools
* **Generated documentation**: Any auto-generated API docs

**Tip**: Write descriptions that help both humans and AI understand your API. Be specific about what operations are available and what the service is for.

### WithDefaultResource

Groups all methods under a resource name. This is one of the most important options for REST APIs:

```go theme={null}
svc := contract.Register[todo.API](impl,
    contract.WithDefaultResource("todos"),
)
```

**What it does**:

Without a resource, your methods would be at the root path (rarely what you want):

```
Create -> POST /create
List   -> GET /list
Get    -> GET /get/{id}
```

With `WithDefaultResource("todos")`, methods get proper RESTful paths:

```
Create -> POST /todos
List   -> GET /todos
Get    -> GET /todos/{id}
Delete -> DELETE /todos/{id}
```

It also affects JSON-RPC method names:

```
Without resource: create, list, get, delete
With resource:    todos.create, todos.list, todos.get, todos.delete
```

**Why "todos" (plural)?**: REST convention uses plural nouns for collections. `/todos` represents the collection of all todos, `/todos/{id}` represents a single todo.

### WithResource

Groups specific methods under a resource name. Use this when one interface manages multiple resources:

```go theme={null}
package api

// API manages both users and orders in one interface
type API interface {
    CreateUser(ctx context.Context, in *CreateUserInput) (*User, error)
    GetUser(ctx context.Context, in *GetUserInput) (*User, error)
    ListUsers(ctx context.Context) (*ListUsersOutput, error)

    CreateOrder(ctx context.Context, in *CreateOrderInput) (*Order, error)
    GetOrder(ctx context.Context, in *GetOrderInput) (*Order, error)
    ListOrders(ctx context.Context) (*ListOrdersOutput, error)
}
```

```go theme={null}
svc := contract.Register[api.API](impl,
    // Group user methods under "users" resource
    contract.WithResource("users", "CreateUser", "GetUser", "ListUsers"),
    // Group order methods under "orders" resource
    contract.WithResource("orders", "CreateOrder", "GetOrder", "ListOrders"),
)

// Result:
// POST /users        -> CreateUser
// GET  /users/{id}   -> GetUser
// GET  /users        -> ListUsers
// POST /orders       -> CreateOrder
// GET  /orders/{id}  -> GetOrder
// GET  /orders       -> ListOrders
```

**Tip**: For cleaner organization, consider using separate packages and interfaces for each resource:

```go theme={null}
// Cleaner: separate packages
todoSvc := contract.Register[todo.API](todoImpl, contract.WithDefaultResource("todos"))
userSvc := contract.Register[user.API](userImpl, contract.WithDefaultResource("users"))

rest.Mount(app.Router, todoSvc)
rest.Mount(app.Router, userSvc)
```

### WithMethodHTTP

Override the HTTP binding for a specific method. Use this when automatic inference doesn't match your needs:

```go theme={null}
svc := contract.Register[todo.API](impl,
    contract.WithDefaultResource("todos"),
    // Custom path with version prefix
    contract.WithMethodHTTP("Create", "POST", "/v1/todos"),
    // Custom action path (non-CRUD operation)
    contract.WithMethodHTTP("Archive", "POST", "/todos/{id}/archive"),
    // Nested resource
    contract.WithMethodHTTP("GetComments", "GET", "/todos/{id}/comments"),
)
```

**Common use cases**:

1. **API versioning**: Add version prefix to paths
   ```go theme={null}
   contract.WithMethodHTTP("Create", "POST", "/v2/todos")
   ```

2. **Custom actions**: Operations that don't fit CRUD
   ```go theme={null}
   contract.WithMethodHTTP("Archive", "POST", "/todos/{id}/archive")
   contract.WithMethodHTTP("Publish", "POST", "/posts/{id}/publish")
   contract.WithMethodHTTP("SendEmail", "POST", "/users/{id}/send-email")
   ```

3. **Nested resources**: Related sub-resources
   ```go theme={null}
   contract.WithMethodHTTP("ListComments", "GET", "/posts/{id}/comments")
   contract.WithMethodHTTP("AddTag", "POST", "/todos/{id}/tags")
   ```

### WithHTTP

Set HTTP bindings for multiple methods at once. Useful when you need to customize many methods:

```go theme={null}
svc := contract.Register[todo.API](impl,
    contract.WithHTTP(map[string]contract.HTTPBinding{
        "Create": {Method: "POST", Path: "/v1/todos"},
        "Get":    {Method: "GET", Path: "/v1/todos/{id}"},
        "List":   {Method: "GET", Path: "/v1/todos"},
        "Update": {Method: "PUT", Path: "/v1/todos/{id}"},
        "Delete": {Method: "DELETE", Path: "/v1/todos/{id}"},
    }),
)
```

This is equivalent to calling `WithMethodHTTP` for each method, but more concise when customizing multiple bindings.

### WithDefaults

Set global defaults for the service that appear in generated specifications:

```go theme={null}
svc := contract.Register[todo.API](impl,
    contract.WithDefaults(contract.Defaults{
        // Base URL for the API (used in OpenAPI servers array)
        BaseURL: "https://api.example.com",
        // Default headers (used in client generation)
        Headers: map[string]string{
            "X-API-Version": "2024-01",
        },
    }),
)
```

**Where defaults are used**:

* **OpenAPI specification**: `servers` array includes the BaseURL
* **Client generators**: Generated clients use these as defaults
* **Documentation**: Shows users the production URL

### WithStreaming

Mark a method as supporting streaming responses:

```go theme={null}
package chat

type API interface {
    // Chat returns a stream of message chunks
    Chat(ctx context.Context, in *ChatInput) (*ChatOutput, error)
}
```

```go theme={null}
svc := contract.Register[chat.API](impl,
    contract.WithDefaultResource("chat"),
    contract.WithStreaming("Chat", contract.StreamSSE),
)
```

**Available streaming modes**:

| Mode          | Description        | Use Case                                      |
| ------------- | ------------------ | --------------------------------------------- |
| `StreamSSE`   | Server-Sent Events | Real-time updates over HTTP (chat, live data) |
| `StreamWS`    | WebSocket          | Bidirectional communication                   |
| `StreamGRPC`  | gRPC streaming     | High-performance service-to-service           |
| `StreamAsync` | Async messaging    | Message queue integration                     |

## The Registered Service

After registration, you get a `*RegisteredService`. This object provides several useful methods:

### Descriptor

Get the service descriptor containing all metadata about your service:

```go theme={null}
svc := contract.Register[todo.API](impl,
    contract.WithName("Todo"),
    contract.WithDefaultResource("todos"),
)

desc := svc.Descriptor()

// Service-level information
fmt.Println("Name:", desc.Name)               // "Todo"
fmt.Println("Description:", desc.Description) // ""

// Iterate through resources
for _, res := range desc.Resources {
    fmt.Printf("Resource: %s\n", res.Name)

    // Iterate through methods in this resource
    for _, m := range res.Methods {
        fmt.Printf("  %s %s -> %s\n",
            m.HTTP.Method,  // "GET", "POST", etc.
            m.HTTP.Path,    // "/todos", "/todos/{id}", etc.
            m.Name,         // "create", "list", etc.
        )
    }
}

// Iterate through registered types
for _, t := range desc.Types {
    fmt.Printf("Type: %s (kind: %s)\n", t.Name, t.Kind)
}
```

**Use cases for Descriptor**:

* Generating custom documentation
* Building admin dashboards that show available endpoints
* Debugging registration issues

### Call

Invoke a method programmatically without going through HTTP:

```go theme={null}
svc := contract.Register[todo.API](impl,
    contract.WithDefaultResource("todos"),
)

ctx := context.Background()
input := &todo.CreateInput{Title: "Buy groceries"}

// Call a method by resource and method name
// Parameters: (ctx, resource, method, input)
result, err := svc.Call(ctx, "todos", "create", input)
if err != nil {
    log.Fatal(err)
}

// Type assert the result
createdTodo := result.(*todo.Todo)
fmt.Println("Created:", createdTodo.ID, createdTodo.Title)
```

**Parameters**:

* `ctx` - Context for the call (timeouts, cancellation)
* `resource` - Resource name as string (e.g., "todos")
* `method` - Method name in lowercase (e.g., "create", "list")
* `input` - Input value, or `nil` for methods without input

**Use cases for Call**:

* Testing without HTTP
* Internal service-to-service calls
* Building CLI tools that use the same service logic

### NewInput

Create a new instance of a method's input type. This is useful for transports and testing:

```go theme={null}
svc := contract.Register[todo.API](impl,
    contract.WithDefaultResource("todos"),
)

// Create a new input instance for the "create" method
input, err := svc.NewInput("todos", "create")
if err != nil {
    log.Fatal(err)
}

// Type assert and populate
createInput := input.(*todo.CreateInput)
createInput.Title = "Learn Go"

// Now use it
result, _ := svc.Call(ctx, "todos", "create", createInput)
```

**Why is this useful?**: Transports need to create input instances before unmarshaling JSON into them. They use `NewInput` to get the correct type, then unmarshal the request body into it.

## How Method Names are Transformed

Contract transforms your Go method names when exposing them as API methods. The transformation is simple:

| Go Interface Method | API Method Name |
| ------------------- | --------------- |
| `Create`            | `create`        |
| `CreateTodo`        | `createTodo`    |
| `GetByID`           | `getByID`       |
| `ListAll`           | `listAll`       |

**Rule**: The first letter is lowercased, the rest stays the same.

This follows the JavaScript/JSON convention of using camelCase for property and method names. When clients call your API, they use these lowercase method names.

## How HTTP Bindings are Inferred

Contract automatically determines the HTTP method and path based on your Go method name. This inference follows REST conventions.

### Method Name to HTTP Verb

Contract looks at how your method name starts to determine the HTTP verb:

| Method Name Starts With                    | HTTP Method | Why                             |
| ------------------------------------------ | ----------- | ------------------------------- |
| `Create`, `Add`, `New`                     | POST        | Creating a new resource         |
| `List`, `All`, `Search`, `Find*s` (plural) | GET         | Retrieving multiple resources   |
| `Get`, `Find`, `Fetch`, `Read`             | GET         | Retrieving a single resource    |
| `Update`, `Edit`, `Modify`, `Set`          | PUT         | Replacing a resource            |
| `Delete`, `Remove`                         | DELETE      | Removing a resource             |
| `Patch`                                    | PATCH       | Partially updating a resource   |
| Everything else                            | POST        | Custom action (default to POST) |

### Path Generation

The path is determined by the method pattern and resource name:

| Method Pattern | Generated Path             | Example             |
| -------------- | -------------------------- | ------------------- |
| Create-like    | `/{resource}`              | POST /todos         |
| List-like      | `/{resource}`              | GET /todos          |
| Get-like       | `/{resource}/{id}`         | GET /todos/{id}     |
| Update-like    | `/{resource}/{id}`         | PUT /todos/{id}     |
| Delete-like    | `/{resource}/{id}`         | DELETE /todos/{id}  |
| Other          | `/{resource}/{methodName}` | POST /todos/archive |

### Complete Example

```go theme={null}
package product

type API interface {
    // Inferred: POST /products
    Create(ctx context.Context, in *CreateInput) (*Product, error)

    // Inferred: GET /products
    List(ctx context.Context) (*ListOutput, error)

    // Inferred: GET /products (same as List, uses query params)
    Search(ctx context.Context, in *SearchInput) (*ListOutput, error)

    // Inferred: GET /products/{id}
    Get(ctx context.Context, in *GetInput) (*Product, error)

    // Inferred: PUT /products/{id}
    Update(ctx context.Context, in *UpdateInput) (*Product, error)

    // Inferred: PATCH /products/{id}
    Patch(ctx context.Context, in *PatchInput) (*Product, error)

    // Inferred: DELETE /products/{id}
    Delete(ctx context.Context, in *DeleteInput) error

    // Inferred: POST /products/archive (custom action)
    Archive(ctx context.Context, in *ArchiveInput) error

    // Inferred: POST /products/publish (custom action)
    Publish(ctx context.Context, in *PublishInput) (*Product, error)
}
```

## Path Parameter Extraction

For methods with `{id}` in the path (Get, Update, Delete), Contract needs to know which field in your input struct contains the ID.

### Default Behavior

Contract looks for these fields in your input struct, in order:

1. **Field with `path:"id"` tag** - Explicit path parameter binding
2. **Field named `ID`** - Standard Go naming
3. **Field ending in `ID`** - Like `TodoID`, `UserID`

### Using the path Tag

The `path` tag explicitly marks a field as a path parameter:

```go theme={null}
package todo

// GetInput identifies which todo to retrieve
type GetInput struct {
    // The path:"id" tag maps this field to {id} in the URL path
    ID string `json:"id" path:"id"`
}

// UpdateInput includes both path parameter and update data
type UpdateInput struct {
    ID        string `json:"id" path:"id"`    // Path parameter
    Title     string `json:"title"`           // Body field
    Completed bool   `json:"completed"`       // Body field
}
```

When a client calls `GET /todos/abc123`, Contract:

1. Extracts `abc123` from the URL path
2. Creates a new `GetInput` instance
3. Sets the `ID` field to `"abc123"`
4. Passes this to your method

### Multiple Path Parameters

For nested resources, you can have multiple path parameters:

```go theme={null}
package comment

// GetInput retrieves a comment on a specific post
type GetInput struct {
    PostID    string `json:"postId" path:"postId"`    // First path param
    CommentID string `json:"commentId" path:"id"`     // Second path param
}
```

```go theme={null}
svc := contract.Register[comment.API](impl,
    contract.WithMethodHTTP("Get", "GET", "/posts/{postId}/comments/{id}"),
)

// GET /posts/post-123/comments/comment-456
// -> GetInput{PostID: "post-123", CommentID: "comment-456"}
```

## Complete Registration Example

Here's a full example demonstrating various registration options with package-based organization:

```go theme={null}
// todo/types.go
package todo

type Todo struct {
    ID        string `json:"id"`
    Title     string `json:"title"`
    Completed bool   `json:"completed"`
}

type CreateInput struct {
    Title string `json:"title"`
}

type GetInput struct {
    ID string `json:"id" path:"id"`
}

type UpdateInput struct {
    ID        string `json:"id" path:"id"`
    Title     string `json:"title"`
    Completed bool   `json:"completed"`
}

type DeleteInput struct {
    ID string `json:"id" path:"id"`
}

type ArchiveInput struct {
    ID string `json:"id" path:"id"`
}

type ListOutput struct {
    Items []*Todo `json:"items"`
    Total int     `json:"total"`
}
```

```go theme={null}
// todo/api.go
package todo

import "context"

type API interface {
    Create(ctx context.Context, in *CreateInput) (*Todo, error)
    List(ctx context.Context) (*ListOutput, error)
    Get(ctx context.Context, in *GetInput) (*Todo, error)
    Update(ctx context.Context, in *UpdateInput) (*Todo, error)
    Delete(ctx context.Context, in *DeleteInput) error
    Archive(ctx context.Context, in *ArchiveInput) error
}
```

```go theme={null}
// todo/service.go
package todo

type Service struct {
    // dependencies...
}

var _ API = (*Service)(nil)

func NewService() *Service {
    return &Service{}
}

// Implement all methods...
```

```go theme={null}
// main.go
package main

import (
    "fmt"

    "github.com/go-mizu/mizu"
    contract "github.com/go-mizu/mizu/contract/v2"
    "github.com/go-mizu/mizu/contract/v2/transport/rest"
    "github.com/go-mizu/mizu/contract/v2/transport/jsonrpc"

    "yourapp/todo"
)

func main() {
    impl := todo.NewService()

    // Register with full configuration
    svc := contract.Register[todo.API](impl,
        // Service metadata
        contract.WithName("Todo"),
        contract.WithDescription("A todo list management API for tracking tasks"),

        // Resource organization - all methods grouped under "todos"
        contract.WithDefaultResource("todos"),

        // Custom HTTP binding for the Archive action
        contract.WithMethodHTTP("Archive", "POST", "/todos/{id}/archive"),

        // Global defaults for generated specs
        contract.WithDefaults(contract.Defaults{
            BaseURL: "https://api.example.com",
        }),
    )

    // Print what was registered (useful for debugging)
    desc := svc.Descriptor()
    fmt.Printf("Service: %s\n", desc.Name)
    fmt.Printf("Description: %s\n", desc.Description)
    fmt.Println("\nEndpoints:")
    for _, res := range desc.Resources {
        for _, m := range res.Methods {
            fmt.Printf("  %-7s %-30s -> %s\n",
                m.HTTP.Method,
                m.HTTP.Path,
                m.Name,
            )
        }
    }

    // Create app and mount transports
    app := mizu.New()
    rest.Mount(app.Router, svc)
    jsonrpc.Mount(app.Router, "/rpc", svc)

    fmt.Println("\nServer starting on http://localhost:8080")
    app.Listen(":8080")
}
```

**Output**:

```
Service: Todo
Description: A todo list management API for tracking tasks

Endpoints:
  POST    /todos                         -> create
  GET     /todos                         -> list
  GET     /todos/{id}                    -> get
  PUT     /todos/{id}                    -> update
  DELETE  /todos/{id}                    -> delete
  POST    /todos/{id}/archive            -> archive

Server starting on http://localhost:8080
```

## Registration Errors

Registration can fail if your interface doesn't follow Contract's rules. Here are common issues:

### Missing Context Parameter

Every method must have `context.Context` as the first parameter:

```go theme={null}
// WRONG: no context parameter
type BadAPI interface {
    Create(in *CreateInput) (*Output, error)  // Missing ctx!
}

// CORRECT: context as first parameter
type GoodAPI interface {
    Create(ctx context.Context, in *CreateInput) (*Output, error)
}
```

**Why context is required**: Context carries request-scoped values like timeouts, cancellation signals, and authentication information. Every API method needs this.

### Invalid Return Type

Methods can only return `(*Output, error)` or just `error`:

```go theme={null}
// WRONG: multiple return values
type BadAPI interface {
    Get(ctx context.Context, in *GetInput) (*User, *Profile, error)  // Too many returns!
}

// CORRECT: wrap multiple values in a struct
type GetUserResult struct {
    User    *User    `json:"user"`
    Profile *Profile `json:"profile"`
}

type GoodAPI interface {
    Get(ctx context.Context, in *GetInput) (*GetUserResult, error)
}
```

### Implementation Doesn't Match Interface

The implementation must implement all methods in the interface with exact signatures:

```go theme={null}
package todo

type API interface {
    Create(ctx context.Context, in *CreateInput) (*Todo, error)
}

type Service struct{}

// MISSING: Service doesn't have Create method
// This causes a compile error when you try to register
```

```go theme={null}
// Compile error:
// cannot use &Service{} (type *Service) as type todo.API in argument to contract.Register:
//     *Service does not implement todo.API (missing Create method)
svc := contract.Register[todo.API](&Service{})
```

**Tip**: Add a compile-time check in your service file:

```go theme={null}
var _ API = (*Service)(nil)  // Fails at compile time if Service doesn't implement API
```

## Best Practices

### Use Descriptive Metadata

Good names and descriptions help users (and AI assistants) understand your API:

```go theme={null}
svc := contract.Register[todo.API](impl,
    contract.WithName("Todo Management"),
    contract.WithDescription(`
        API for managing todo items. Supports full CRUD operations:
        - Create new todos with a title
        - List all todos with pagination
        - Get, update, or delete specific todos by ID
        - Archive completed todos
    `),
)
```

### Organize with Separate Packages

Prefer separate packages over one giant interface:

```go theme={null}
// GOOD: Separate packages for each domain
import (
    "yourapp/todo"
    "yourapp/user"
    "yourapp/order"
)

todoSvc := contract.Register[todo.API](todoImpl, contract.WithDefaultResource("todos"))
userSvc := contract.Register[user.API](userImpl, contract.WithDefaultResource("users"))
orderSvc := contract.Register[order.API](orderImpl, contract.WithDefaultResource("orders"))

rest.Mount(app.Router, todoSvc)
rest.Mount(app.Router, userSvc)
rest.Mount(app.Router, orderSvc)
```

### Create a Register Function

Keep registration logic close to the implementation:

```go theme={null}
// todo/register.go
package todo

import contract "github.com/go-mizu/mizu/contract/v2"

// Register creates a registered service with standard configuration.
// This keeps registration options close to the service definition.
func Register(impl API) *contract.RegisteredService {
    return contract.Register[API](impl,
        contract.WithName("Todo"),
        contract.WithDescription("Todo management API"),
        contract.WithDefaultResource("todos"),
    )
}
```

```go theme={null}
// main.go
func main() {
    impl := todo.NewService(db)
    svc := todo.Register(impl)  // Clean and encapsulated

    rest.Mount(app.Router, svc)
}
```

## Common Questions

### Can I register multiple services?

Yes! Register each service separately and mount them all:

```go theme={null}
todoSvc := contract.Register[todo.API](todoImpl, contract.WithDefaultResource("todos"))
userSvc := contract.Register[user.API](userImpl, contract.WithDefaultResource("users"))

// Mount both on the same router
rest.Mount(app.Router, todoSvc)
rest.Mount(app.Router, userSvc)

// Both are accessible:
// GET /todos, POST /todos, etc.
// GET /users, POST /users, etc.
```

### Can I modify registration after it's created?

No, registration is immutable. If you need different options, create a new registration:

```go theme={null}
// Create different registrations for different purposes
devSvc := contract.Register[todo.API](impl,
    contract.WithDefaultResource("todos"),
)

prodSvc := contract.Register[todo.API](impl,
    contract.WithDefaultResource("todos"),
    contract.WithDefaults(contract.Defaults{
        BaseURL: "https://api.example.com",
    }),
)
```

### How do I access the original implementation?

The registered service wraps your implementation. Keep a reference if you need direct access:

```go theme={null}
impl := todo.NewService(db)
svc := contract.Register[todo.API](impl)

// svc is the registered wrapper
// impl is your original implementation

// If you need to call internal methods directly:
impl.SomeInternalMethod()
```

## What's Next?

Now that you understand registration:

* **[Type System](/contract/types)** - How Go types are converted to JSON schemas
* **[Transports](/contract/transports-overview)** - Mount your service on REST, JSON-RPC, or MCP
* **[Error Handling](/contract/errors)** - Handle errors consistently across protocols
