> For the complete documentation index, see [llms.txt](https://azutopia.gitbook.io/azu/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://azutopia.gitbook.io/azu/concepts/contracts.md).

# Contracts

This document explains the contract pattern in Azu, where explicit request and response types create clear interfaces between components.

## What are Contracts?

Contracts are type definitions that specify the shape of data flowing through your application:

* **Request contracts** define expected input
* **Response contracts** define expected output

Together, they create a clear API contract that's enforced by the compiler.

## The Contract Pattern

### Traditional Approach

Without contracts, data shapes are implicit:

```ruby
def create
  # What fields are expected?
  name = params[:name]
  email = params[:email]

  # What if name is missing? Runtime error
  # What if email is wrong type? Runtime error
end
```

### Contract Approach

With contracts, expectations are explicit:

```crystal
struct CreateUserRequest
  include Azu::Request

  getter name : String
  getter email : String
end
```

Benefits:

* Self-documenting
* Validated automatically
* Type-checked at compile time

## Request Contracts

Request contracts define what data endpoints accept:

```crystal
struct CreateUserRequest
  include Azu::Request

  getter name : String
  getter email : String
  getter age : Int32?  # Optional

  def initialize(@name = "", @email = "", @age = nil)
  end

  validate name, presence: true, length: {min: 2}
  validate email, presence: true, format: /@/
end
```

### Components

1. **Fields** - Properties that will be populated
2. **Types** - Crystal types (String, Int32, etc.)
3. **Optionality** - Use `?` for optional fields
4. **Validations** - Rules applied before processing

### Parsing

Request contracts automatically parse:

* JSON bodies (`application/json`)
* Form data (`application/x-www-form-urlencoded`)
* Multipart forms (`multipart/form-data`)

## Response Contracts

Response contracts define what endpoints return:

```crystal
struct UserResponse
  include Azu::Response

  def initialize(@user : User)
  end

  def render
    {
      id: @user.id,
      name: @user.name,
      email: @user.email
    }.to_json
  end
end
```

### Components

1. **Constructor** - Accepts data to render
2. **Render method** - Produces output string
3. **Content type** - Implicit or explicit

### Return Type Enforcement

The compiler ensures you return the declared type:

```crystal
struct MyEndpoint
  include Azu::Endpoint(Request, UserResponse)

  def call : UserResponse
    # Must return UserResponse
    "string"  # Compile error!
  end
end
```

## Contract Benefits

### 1. Self-Documentation

Contracts document the API:

```crystal
struct SearchRequest
  include Azu::Request

  getter query : String           # Search term
  getter page : Int32 = 1         # Page number
  getter per_page : Int32 = 20    # Results per page
  getter sort : String = "date"   # Sort field
end
```

Reading the request tells you exactly what the API accepts.

### 2. Validation

Validations run before your code:

```crystal
struct CreateOrderRequest
  include Azu::Request

  getter items : Array(OrderItem)
  getter shipping_address : String
  getter payment_method : String

  validate items, presence: true
  validate shipping_address, presence: true
  validate payment_method, inclusion: {in: ["card", "paypal", "bank"]}

  def validate
    super
    if items.empty?
      errors << Error.new(:items, "must have at least one item")
    end
  end
end
```

Invalid requests are rejected before reaching your endpoint.

### 3. Type Safety

Types are enforced at compile time:

```crystal
def call
  # age is Int32?, not String
  if age = create_user_request.age
    validate_age(age)  # Compiler knows it's Int32
  end
end
```

### 4. Refactoring Confidence

Changing contracts triggers compile errors:

```crystal
# Before
struct UserResponse
  def initialize(@user : User)
  end
end

# After - add required field
struct UserResponse
  def initialize(@user : User, @permissions : Array(String))
  end
end

# All usages that don't provide permissions will fail to compile
```

## Empty Contracts

For endpoints without body data:

```crystal
struct GetUserEndpoint
  include Azu::Endpoint(EmptyRequest, UserResponse)

  get "/users/:id"

  def call : UserResponse
    # No request body to parse
    # Use params for route parameters
    id = params["id"]
  end
end
```

For endpoints without response body:

```crystal
struct DeleteUserEndpoint
  include Azu::Endpoint(EmptyRequest, Azu::Response::Empty)

  delete "/users/:id"

  def call
    User.find(params["id"]).destroy
    status 204
    Azu::Response::Empty.new
  end
end
```

## Composition

Contracts can reference other types:

```crystal
struct OrderItem
  include JSON::Serializable
  property product_id : Int64
  property quantity : Int32
end

struct CreateOrderRequest
  include Azu::Request

  getter items : Array(OrderItem)
  getter notes : String?
end
```

## Contract Versioning

For API versioning, create separate contracts:

```crystal
module V1
  struct UserResponse
    include Azu::Response
    # V1 format
  end
end

module V2
  struct UserResponse
    include Azu::Response
    # V2 format with additional fields
  end
end
```

## Best Practices

1. **One contract per use case**

   ```crystal
   struct CreateUserRequest    # For creation
   struct UpdateUserRequest    # For updates (might have optional fields)
   ```
2. **Use meaningful names**

   ```crystal
   struct SearchProductsRequest  # Clear purpose
   struct ProductListResponse    # Clear output
   ```
3. **Keep contracts focused**

   ```crystal
   # Good: focused response
   struct UserResponse
     def initialize(@user : User)
     end
   end

   # Avoid: kitchen-sink response
   struct BigResponse
     def initialize(@user, @posts, @comments, @notifications, ...)
     end
   end
   ```

## See Also

* [Endpoints](/azu/concepts/endpoints.md)
* [Why Contracts](/azu/design-decisions/why-contracts.md)
* [Request Reference](/azu/api-reference/request.md)
* [Response Reference](/azu/api-reference/response.md)


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://azutopia.gitbook.io/azu/concepts/contracts.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
