Skip to content

Inputs

Inputs are typed parameters that clients provide when calling queries. Hyperterse validates inputs, applies defaults for optional fields, and safely injects them into SQL statements. They serve three purposes:

  1. Validation — Ensure data types match before execution
  2. Documentation — Generate OpenAPI schemas and LLM descriptions
  3. Security — Properly escape values to prevent SQL injection
queries:
search-users:
use: main_db
description: "Search users by name and role"
statement: |
SELECT id, name, email, role
FROM users
WHERE name LIKE {{ inputs.searchTerm }}
AND role = {{ inputs.role }}
LIMIT {{ inputs.limit }}
inputs:
searchTerm:
type: string
description: "Search term (supports % wildcards)"
role:
type: string
description: "User role to filter by"
optional: true
default: "user"
limit:
type: int
description: "Maximum results to return"
optional: true
default: "20"
PropertyRequiredDescription
typeYesData type (see below)
descriptionYesHuman-readable description
optionalNoWhether the input is optional (default: false)
defaultNoDefault value for optional inputs
TypeDescriptionExample Value
stringText values"hello world"
intInteger numbers (64-bit)42, -100
floatFloating-point numbers3.14, -0.5
booleanTrue/false valuestrue, false
uuidUUID strings"550e8400-e29b-41d4-a716-446655440000"
datetimeISO 8601 datetime (RFC3339)"2024-01-15T10:30:00Z"

Reference inputs in SQL statements using the template syntax:

{{ inputs.fieldName }}
statement: |
SELECT * FROM users WHERE id = {{ inputs.userId }}
inputs:
userId:
type: int
description: 'User ID'

When called with {"userId": 123}, the statement becomes:

SELECT * FROM users WHERE id = 123

String values are automatically quoted and escaped:

statement: |
SELECT * FROM users WHERE email = {{ inputs.email }}
inputs:
email:
type: string
description: 'Email address'

When called with {"email": "alice@example.com"}:

SELECT * FROM users WHERE email = 'alice@example.com'
statement: |
SELECT * FROM products
WHERE category = {{ inputs.category }}
AND price BETWEEN {{ inputs.minPrice }} AND {{ inputs.maxPrice }}
AND in_stock = {{ inputs.inStock }}
ORDER BY price ASC
inputs:
category:
type: string
description: 'Product category'
minPrice:
type: float
description: 'Minimum price'
maxPrice:
type: float
description: 'Maximum price'
inStock:
type: boolean
description: 'Only show in-stock items'
statement: |
SELECT * FROM events
WHERE created_at >= {{ inputs.startDate }}
AND created_at <= {{ inputs.endDate }}
inputs:
startDate:
type: datetime
description: 'Start of date range'
endDate:
type: datetime
description: 'End of date range'

Call with ISO 8601 format:

{
"startDate": "2024-01-01T00:00:00Z",
"endDate": "2024-01-31T23:59:59Z"
}

Mark inputs as optional and provide default values:

inputs:
limit:
type: int
description: 'Number of results'
optional: true
default: '20'
sortOrder:
type: string
description: 'Sort direction (asc or desc)'
optional: true
default: 'desc'
queries:
list-users:
use: main_db
description: 'List users with optional pagination'
statement: |
SELECT id, name, email
FROM users
ORDER BY created_at DESC
LIMIT {{ inputs.limit }}
OFFSET {{ inputs.offset }}
inputs:
limit:
type: int
description: 'Page size'
optional: true
default: '20'
offset:
type: int
description: 'Number of items to skip'
optional: true
default: '0'

This can be called with no inputs:

Terminal window
curl -X POST http://localhost:8080/query/list-users \
-H "Content-Type: application/json" \
-d '{}'

Or with specific values:

Terminal window
curl -X POST http://localhost:8080/query/list-users \
-H "Content-Type: application/json" \
-d '{"limit": 50, "offset": 100}'

Hyperterse validates all inputs before executing queries:

Inputs must match their declared types:

// Valid for type: int
{"userId": 123}
// Invalid - string provided for int
{"userId": "abc"}

Missing required inputs return an error:

{
"success": false,
"error": "validation error for field 'userId': required input 'userId' is missing",
"results": []
}

Extra inputs not defined in the schema are rejected:

{
"success": false,
"error": "validation error: unknown input field 'unknownField' provided",
"results": []
}

Hyperterse protects against SQL injection through:

  1. Type enforcement — Only valid types are accepted
  2. String escaping — Single quotes are escaped in string values
  3. Template validation — All {{ inputs.x }} references must be defined

Use clear, descriptive input names:

# Good
inputs:
userId:
type: int
emailAddress:
type: string
createdAfter:
type: datetime
# Less clear
inputs:
id:
type: int
str:
type: string
dt:
type: datetime

Write descriptions that help API consumers understand what to provide:

inputs:
searchTerm:
type: string
description: 'Search term to match against user names. Use % as wildcard.'
limit:
type: int
description: 'Maximum number of results (1-100)'
optional: true
default: '20'

Choose defaults that make sense for most use cases:

inputs:
limit:
type: int
default: '20' # Reasonable page size
sortOrder:
type: string
default: 'desc' # Most recent first