Skip to main content

What are Models?

Models in the Zitadel Ruby SDK are Ruby classes that represent data structures returned from or sent to the Zitadel API. They provide a structured way to work with Zitadel resources such as users, organizations, and applications. All model classes are located in the Zitadel::Client::Models module and are automatically generated from the Zitadel OpenAPI specification.

How Models Work

Models provide several key features:

Attribute Accessors

Each model exposes attributes as Ruby attr_accessors, allowing you to read and write properties using standard Ruby syntax:
user = Zitadel::Client::Models::UserServiceUser.new
user.user_id = "123456789"
user.username = "john.doe"
puts user.user_id # => "123456789"

Initialization from Hash

Models can be initialized from a hash of attributes:
user = Zitadel::Client::Models::UserServiceHumanUser.new(
  user_id: "123456789",
  username: "john.doe",
  profile: {
    given_name: "John",
    family_name: "Doe"
  }
)

JSON Mapping

Models automatically handle conversion between Ruby naming conventions (snake_case) and JSON naming conventions (camelCase):
  • Ruby: user_id, preferred_login_name
  • JSON: userId, preferredLoginName
This mapping is handled transparently by the SDK.

Serialization and Deserialization

Converting to Hash/JSON

Models provide methods to convert to Ruby hashes and JSON:
user = Zitadel::Client::Models::UserServiceUser.new(
  user_id: "123",
  username: "john.doe"
)

# Convert to hash
hash = user.to_hash
# => {"userId" => "123", "username" => "john.doe"}

# Convert to JSON string
json = user.to_hash.to_json

Building from API Response

The SDK automatically deserializes API responses into model objects:
# When you call an API method, responses are automatically converted to models
response = client.user_service.get_user_by_id(user_id: "123")
user = response.user # Already a UserServiceUser model instance

Manual Deserialization

You can also manually deserialize data:
data = {
  "userId" => "123",
  "username" => "john.doe",
  "state" => "USER_STATE_ACTIVE"
}

user = Zitadel::Client::Models::UserServiceUser.build_from_hash(data)

Type Safety

Each model defines its attribute types through the openapi_types method:
Zitadel::Client::Models::UserServiceUser.openapi_types
# => {
#   user_id: 'String',
#   details: 'UserServiceDetails',
#   state: 'UserServiceUserState',
#   login_names: 'Array<String>',
#   human: 'UserServiceHumanUser',
#   machine: 'UserServiceMachineUser'
# }
The SDK uses this type information to properly deserialize nested objects and arrays.

Nested Models

Many models contain nested model objects. For example, UserServiceUser can contain a UserServiceHumanUser object:
user = response.user
if user.human
  # Access nested profile information
  profile = user.human.profile
  puts "Name: #{profile.given_name} #{profile.family_name}"
  
  # Access nested email information
  email = user.human.email
  puts "Email: #{email.email} (verified: #{email.is_verified})"
end

Common Patterns

Checking User Type

user = response.user

if user.human
  # Handle human user
  puts "Human user: #{user.human.profile.display_name}"
elsif user.machine
  # Handle machine user
  puts "Machine user: #{user.machine.name}"
end

Working with Arrays

Many models contain array attributes:
user = response.user

# Iterate over login names
user.login_names.each do |login_name|
  puts "Login name: #{login_name}"
end

# Access OIDC redirect URIs
application = response.application
if application.oidc_configuration
  application.oidc_configuration.redirect_uris.each do |uri|
    puts "Redirect URI: #{uri}"
  end
end

Handling Timestamps

Timestamp fields are automatically parsed into Ruby Time objects:
application = response.application
puts "Created: #{application.creation_date.strftime('%Y-%m-%d %H:%M:%S')}"
puts "Modified: #{application.change_date.strftime('%Y-%m-%d %H:%M:%S')}"

Model Categories

The SDK includes models organized by resource type:

Error Handling

Models validate input during initialization:
begin
  user = Zitadel::Client::Models::UserServiceUser.new(
    invalid_attribute: "value"
  )
rescue ArgumentError => e
  puts e.message
  # => "`invalid_attribute` is not a valid attribute in `Zitadel::Client::Models::UserServiceUser`"
end

Best Practices

  1. Use type information - Check the openapi_types to understand expected data types
  2. Handle nil values - Not all attributes are always present; check for nil before accessing nested objects
  3. Use build_from_hash - When working with raw API data, use build_from_hash for proper type conversion
  4. Leverage attribute mapping - Let the SDK handle JSON naming conversions automatically
  5. Check nullable attributes - Use openapi_nullable to see which attributes can be nil

Next Steps

Build docs developers (and LLMs) love