Skip to main content
This quickstart guide walks you through authenticating with Zitadel and making your first API call. You’ll create a user using the SDK in just a few steps.

Prerequisites

Before you begin, ensure you have:
  • Ruby 3.0+ installed
  • The zitadel-client gem installed (see installation guide)
  • A Zitadel account and instance URL
  • API credentials (we’ll cover how to get these)

Getting Your Credentials

You need credentials to authenticate with Zitadel. Choose one of the following methods:
1

Log into Zitadel Console

Navigate to your Zitadel instance (e.g., https://example.zitadel.cloud)
2

Navigate to Personal Access Tokens

Go to your user profile → Personal Access Tokens
3

Create New Token

Click “New” and give it a name like “Ruby SDK Development”
4

Copy the Token

Save the generated token securely - you won’t be able to see it again

Your First Integration

Let’s create a complete example that authenticates and creates a user.
1

Create a Ruby Script

Create a new file called zitadel_example.rb:
zitadel_example.rb
#!/usr/bin/env ruby
# frozen_string_literal: true

require 'zitadel-client'
require 'securerandom'

# Your Zitadel instance URL
ZITADEL_URL = "https://example.zitadel.cloud"

# Your authentication credentials (choose one method below)
AUTH_TOKEN = "your-personal-access-token-here"
2

Choose Your Authentication Method

Select one of the following authentication methods:
# Initialize client with Personal Access Token
client = Zitadel::Client::Zitadel.with_access_token(
  ZITADEL_URL,
  AUTH_TOKEN
)

puts "✓ Authenticated with Personal Access Token"
3

Make Your First API Call

Let’s create a user to verify everything works:
begin
  # Create a request to add a human user
  request = Zitadel::Client::Models::UserServiceAddHumanUserRequest.new(
    username: "testuser_#{SecureRandom.hex(4)}",
    profile: Zitadel::Client::Models::UserServiceSetHumanProfile.new(
      given_name: 'Jane',
      family_name: 'Doe'
    ),
    email: Zitadel::Client::Models::UserServiceSetHumanEmail.new(
      email: "jane.doe.#{SecureRandom.hex(4)}@example.com"
    )
  )
  
  # Call the API
  response = client.users.add_human_user(request)
  
  puts "\n✅ User created successfully!"
  puts "User ID: #{response.user_id}"
  puts "Username: #{request.username}"
  puts "Email: #{request.email.email}"
  
rescue Zitadel::Client::ApiError => e
  puts "\n❌ API Error: #{e.message}"
  puts "Status Code: #{e.code}"
rescue StandardError => e
  puts "\n❌ Error: #{e.message}"
end
4

Run Your Script

Execute the script:
ruby zitadel_example.rb
You should see output like:
✓ Authenticated with Personal Access Token

✅ User created successfully!
User ID: 123456789012345678
Username: testuser_a3f9
Email: [email protected]

Complete Example with All Authentication Methods

Here’s a complete script demonstrating all three authentication methods:
complete_example.rb
#!/usr/bin/env ruby
# frozen_string_literal: true

require 'zitadel-client'
require 'securerandom'

ZITADEL_URL = "https://example.zitadel.cloud"

def create_test_user(client, auth_method)
  request = Zitadel::Client::Models::UserServiceAddHumanUserRequest.new(
    username: SecureRandom.hex,
    profile: Zitadel::Client::Models::UserServiceSetHumanProfile.new(
      given_name: 'John',
      family_name: 'Doe'
    ),
    email: Zitadel::Client::Models::UserServiceSetHumanEmail.new(
      email: "john.doe.#{SecureRandom.hex}@example.com"
    )
  )
  
  response = client.users.add_human_user(request)
  puts "✅ [#{auth_method}] User created: #{response.user_id}"
  response
rescue Zitadel::Client::ApiError => e
  puts "❌ [#{auth_method}] API Error: #{e.message} (#{e.code})"
  nil
end

# Example 1: Personal Access Token
if ENV['ZITADEL_PAT']
  puts "\n=== Testing Personal Access Token ==="
  client = Zitadel::Client::Zitadel.with_access_token(
    ZITADEL_URL,
    ENV['ZITADEL_PAT']
  )
  create_test_user(client, "PAT")
end

# Example 2: Private Key JWT
if ENV['ZITADEL_KEY_FILE']
  puts "\n=== Testing Private Key JWT ==="
  client = Zitadel::Client::Zitadel.with_private_key(
    ZITADEL_URL,
    ENV['ZITADEL_KEY_FILE']
  )
  create_test_user(client, "Private Key")
end

# Example 3: Client Credentials
if ENV['ZITADEL_CLIENT_ID'] && ENV['ZITADEL_CLIENT_SECRET']
  puts "\n=== Testing Client Credentials ==="
  client = Zitadel::Client::Zitadel.with_client_credentials(
    ZITADEL_URL,
    ENV['ZITADEL_CLIENT_ID'],
    ENV['ZITADEL_CLIENT_SECRET']
  )
  create_test_user(client, "Client Credentials")
end
Run with environment variables:
# Using Personal Access Token
export ZITADEL_PAT="your-token"
ruby complete_example.rb

# Using Private Key JWT
export ZITADEL_KEY_FILE="/path/to/service-account.json"
ruby complete_example.rb

# Using Client Credentials
export ZITADEL_CLIENT_ID="your-client-id"
export ZITADEL_CLIENT_SECRET="your-client-secret"
ruby complete_example.rb

More Examples

Retrieve User by ID

user_id = "123456789012345678"

request = Zitadel::Client::Models::UserServiceGetUserByIDRequest.new(
  user_id: user_id
)

response = client.users.get_user_by_id(request)

puts "User: #{response.user.human.profile.given_name} #{response.user.human.profile.family_name}"
puts "Email: #{response.user.human.email.email}"
puts "Created: #{response.user.details.creation_date}"

List All Users

request = Zitadel::Client::Models::UserServiceListUsersRequest.new(
  queries: []
)

response = client.users.list_users(request)

puts "Total users: #{response.details.total_result}"

response.result.each do |user|
  if user.human
    puts "- #{user.human.profile.given_name} #{user.human.profile.family_name} (#{user.human.email.email})"
  end
end

Update User Email

user_id = "123456789012345678"
new_email = "[email protected]"

update_request = Zitadel::Client::Models::UserServiceUpdateHumanUserRequest.new(
  user_id: user_id,
  email: Zitadel::Client::Models::UserServiceSetHumanEmail.new(
    email: new_email
  )
)

client.users.update_human_user(update_request)
puts "✅ Email updated to #{new_email}"

Get General Settings

response = client.settings.get_general_settings

puts "Instance Settings:"
puts "- Default Language: #{response.default_language}"
puts "- Default Org ID: #{response.default_org_id}"

Error Handling

Always handle errors appropriately:
begin
  response = client.users.get_user_by_id(
    Zitadel::Client::Models::UserServiceGetUserByIDRequest.new(
      user_id: "non-existent-id"
    )
  )
rescue Zitadel::Client::ApiError => e
  # API returned an error (4xx, 5xx)
  puts "API Error: #{e.message}"
  puts "HTTP Status: #{e.code}"
  puts "Response body: #{e.response_body}"
rescue Zitadel::Client::ZitadelError => e
  # Zitadel-specific error
  puts "Zitadel Error: #{e.message}"
rescue StandardError => e
  # Other errors (network, etc.)
  puts "Unexpected error: #{e.message}"
end

Configuration and Debugging

Enable debug mode to see detailed HTTP logs:
client = Zitadel::Client::Zitadel.with_access_token(
  ZITADEL_URL,
  AUTH_TOKEN
) do |config|
  # Enable debugging
  config.debugging = true
  
  # Set custom logger
  config.logger = Logger.new(STDOUT)
  config.logger.level = Logger::DEBUG
  
  # Set timeout (seconds)
  config.timeout = 30
end
This will output detailed information about each HTTP request and response:
[DEBUG] GET https://example.zitadel.cloud/v2/users/123456789012345678
[DEBUG] Request Headers: {"Authorization"=>"Bearer ***", "User-Agent"=>"..."}
[DEBUG] Response Status: 200
[DEBUG] Response Body: {"user": {...}}

Advanced Configuration

Customize the SDK behavior:
client = Zitadel::Client::Zitadel.with_private_key(
  ZITADEL_URL,
  "service-account.json"
) do |config|
  # Timeouts
  config.timeout = 60  # 60 seconds (0 = no timeout)
  
  # SSL Configuration
  config.verify_ssl = true
  config.verify_ssl_host = true
  config.ssl_ca_cert = '/path/to/ca-bundle.crt'
  
  # Client-side validation
  config.client_side_validation = true
  
  # Custom User-Agent
  config.user_agent = "MyApp/1.0.0 #{config.user_agent}"
  
  # Logging
  config.debugging = false
  config.logger = Rails.logger if defined?(Rails)
end

Next Steps

Now that you’ve made your first API calls, explore more features:

Authentication Guide

Deep dive into authentication methods and best practices

API Reference

Explore all available API methods and models

User Management

Learn advanced user management techniques

Error Handling

Handle errors gracefully in production

Common Issues

Problem: ApiError: Unauthorized (401)Solutions:
  • Verify your token/credentials are correct
  • Check that the token hasn’t expired
  • Ensure the service account has necessary permissions
  • Confirm your instance URL is correct
Problem: ApiError: Forbidden (403)Solutions:
  • Grant necessary roles to your service account
  • Check organization context (some operations require org scope)
  • Verify the resource exists and you have access
Problem: ApiError: User already existsSolution: Use a unique username or email. The example uses SecureRandom.hex to generate unique values.
Problem: Timeout::Error or connection errorsSolutions:
  • Check your network connectivity
  • Verify firewall settings
  • Increase timeout: config.timeout = 60
  • Confirm your Zitadel instance URL is reachable

Getting Help

If you encounter issues:

Build docs developers (and LLMs) love