Carrier
Part Two · Core Language Model
Chapter 71 min read

Types and API Contracts

Carrier type declarations define structured values used for inputs, outputs, and reusable contract shapes. A model describes persistence. A type describes a contract. They are related — but not the same thing.

Named Request and Response Types

Enterprise APIs should not rely on anonymous, improvised shapes. Named types give teams a shared vocabulary. The hello-carrier example uses named types extensively for inputs, responses, and reusable shapes:

excerpt
type RegisterRequest {
email: String @email
name: String @length(min: 2, max: 100)
password: String @length(min: 8)
}
type AuthTokens {
access_token: String
refresh_token: String
}
type MeResponse {
id: Int
email: String
name: String
}

A CreatePatientRequest, EncounterSummary, SubmitQuestionnaireResponse, or ClaimDecisionResult carries meaning. It can be reviewed. It can be documented. It can be versioned. It appears in generated OpenAPI output. Named types help API consumers understand intent, and they help architects detect when services are leaking internal implementation details.

Stable Contract Design

Stable contracts are designed around consumer needs, not database convenience. It is tempting to return model fields directly from routes. That is sometimes acceptable for internal tools or simple resources, but enterprise APIs often need a stronger boundary. A stable response type can hide internal fields, rename fields into business language, combine values from multiple internal structures, and preserve compatibility while the model evolves.

Using Json for Flexible Operational Envelopes

Carrier supports Json for cases where rigid structure is not the best fit — operational envelopes, flexible payloads, schedule-triggered jobs, integration metadata. But Json should not become a shortcut around contract design. If a payload represents a stable business operation, prefer a named type. Use Json when flexibility is intentional, not when the domain is merely unclear.

Versioning API Shapes

Carrier can generate OpenAPI, but teams must still decide how contracts evolve. The safest enterprise approach is to treat breaking changes as exceptional. Add fields where possible. Avoid changing field meaning. Do not reuse names for different concepts. When replacement is required, introduce the new contract beside the old one and give consumers a migration path.

Contents