Documentation for LLMs on building APIs with the Apia framework
Argument sets define reusable groups of input parameters. They are used to organize endpoint arguments into logical groups, especially for create and update operations.
module MyAPI
module ArgumentSets
class UserCreateProperties < Apia::ArgumentSet
name "User creation properties"
description "The properties required to create a user"
argument :first_name, :string, required: true
argument :last_name, :string, required: true
argument :email_address, :string, required: true
argument :time_zone, :string
end
end
end
class CreateEndpoint < BaseEndpoint
argument :properties, ArgumentSets::UserCreateProperties, required: true
def call
props = request.arguments[:properties].to_hash
user = User.create!(props)
response.add_field :user, user
end
end
requiredMarks the argument as mandatory. A MissingArgumentError is raised if it’s not provided.
argument :name, :string, required: true
defaultSets a default value when the argument is not provided.
argument :active, :boolean, default: true
argument :page, :integer, default: 1
descriptionAdds a description for schema/documentation.
argument :email, :string, required: true, description: "The user's email address"
Wrap the type in brackets to accept an array:
argument :tags, [:string]
argument :role_names, [:string]
argument :networks, [:string]
Arguments can reference other argument sets for nesting:
argument :password, ArgumentSets::PasswordProperties
argument :totp_registrations, [ArgumentSets::TOTPRegistrationProperties]
Arguments can use enum types to restrict valid values:
argument :time_zone, Enums::TimeZoneEnum
argument :color_scheme, Enums::ColorSchemeEnum
Add custom validation logic with a name and block. The block receives the argument value and should return a truthy value for valid input:
argument :age, :integer do
validation(:must_be_positive) { |value| value.positive? }
end
argument :per_page, :integer, default: 30 do
validation(:greater_than_zero) { |o| o.positive? }
validation(:max_100) { |o| o <= 100 }
end
In endpoint actions, arguments are accessed through request.arguments:
def call
# Access a top-level argument
name = request.arguments[:name]
# Access a nested argument set, converting to a plain hash
props = request.arguments[:properties].to_hash
# Access individual nested arguments
first_name = request.arguments[:properties][:first_name]
# Check if an argument was provided (vs not sent at all)
if request.arguments[:properties].has?(:time_zone)
# time_zone was explicitly provided (could be nil)
end
end
class UserUpdateProperties < Apia::ArgumentSet
argument :first_name, :string
argument :last_name, :string
argument :time_zone, :string
end
class OrganizationCreateProperties < Apia::ArgumentSet
argument :name, :string, required: true
argument :identifier, :string
argument :time_zone, Enums::TimeZoneEnum
end
class UserCreationProperties < Apia::ArgumentSet
name "User creation properties"
description "The properties required to create a user"
argument :first_name, :string, required: true
argument :last_name, :string, required: true
argument :email_address, :string, required: true
argument :time_zone, :string
argument :password, ArgumentSets::PasswordProperties
argument :totp_registrations, [ArgumentSets::TOTPRegistrationProperties]
argument :recovery_codes, [ArgumentSets::RecoveryCodeProperties]
end
A pattern for accepting arbitrary key-value pairs:
class KeyValue < Apia::ArgumentSet
argument :key, :string, required: true
argument :value, :string
class << self
def to_hash(arguments)
arguments.to_h { |a| [a[:key], a[:value]] }
end
end
end
Usage in an endpoint:
argument :metadata, [ArgumentSets::KeyValue]
def call
metadata = ArgumentSets::KeyValue.to_hash(request.arguments[:metadata])
end