Skip to main content
Parameter validators define the input parameters for your Tinybird pipes and endpoints. They provide full TypeScript type inference and runtime validation.

Basic Usage

import { p } from '@tinybirdco/sdk';

const params = {
  user_id: p.string(),
  limit: p.int32().optional(10),
  start_date: p.dateTime().describe('Start of date range'),
};

String Parameters

p.string()

String parameter.
user_id: p.string()

p.uuid()

UUID parameter.
id: p.uuid()

Integer Parameters

p.int8()

8-bit signed integer

p.int16()

16-bit signed integer

p.int32()

32-bit signed integer

p.int64()

64-bit signed integer

p.uint8()

8-bit unsigned integer

p.uint16()

16-bit unsigned integer

p.uint32()

32-bit unsigned integer

p.uint64()

64-bit unsigned integer

Float Parameters

p.float32()

32-bit floating point parameter.
threshold: p.float32()

p.float64()

64-bit floating point parameter.
amount: p.float64()

Boolean

p.boolean()

Boolean parameter.
is_active: p.boolean()

Date/Time Parameters

p.date()

Date parameter in YYYY-MM-DD format.
birth_date: p.date() // "2024-01-15"

p.dateTime()

DateTime parameter in YYYY-MM-DD HH:MM:SS format.
start_date: p.dateTime() // "2024-01-15 10:30:00"

p.dateTime64()

DateTime64 parameter with fractional seconds.
timestamp: p.dateTime64() // "2024-01-15 10:30:00.123"

Array Parameters

p.array(element, separator?)

Array parameter - values can be passed as comma-separated or repeated params.
ids: p.array(p.string())
scores: p.array(p.int32())
// Can be passed as: ?ids=a,b,c or ?ids=a&ids=b&ids=c

Special Parameters

p.column()

Column reference parameter - allows dynamic column selection.
group_by: p.column()
// Use with caution as it can affect query safety
Use p.column() carefully as it allows dynamic column selection which can affect query safety and performance.

p.json()

JSON parameter for passing complex structured data.
filters: p.json()

Modifiers

.optional(defaultValue?)

Make a parameter optional with an optional default value.
limit: p.int32().optional(10)
offset: p.int32().optional(0)
status: p.string().optional() // no default
When a parameter is optional:
  • If a default value is provided, the parameter type remains the base type
  • If no default value is provided, the parameter type becomes T | undefined

.required()

Explicitly mark a parameter as required (this is the default).
user_id: p.string().required()

.describe(description)

Add a description for documentation purposes.
start_date: p.dateTime().describe('Start of date range')
end_date: p.dateTime().describe('End of date range')
limit: p.int32().optional(10).describe('Maximum number of results')

Complete Example

import { defineEndpoint, node, t, p, type InferParams } from '@tinybirdco/sdk';

export const topPages = defineEndpoint('top_pages', {
  description: 'Get the most visited pages',
  params: {
    start_date: p.dateTime().describe('Start of date range'),
    end_date: p.dateTime().describe('End of date range'),
    limit: p.int32().optional(10).describe('Maximum number of results'),
    country: p.string().optional().describe('Filter by country code'),
  },
  nodes: [
    node({
      name: 'aggregated',
      sql: `
        SELECT pathname, count() AS views
        FROM page_views
        WHERE timestamp >= {{DateTime(start_date)}}
          AND timestamp <= {{DateTime(end_date)}}
          {% if defined(country) %}
          AND country = {{String(country)}}
          {% end %}
        GROUP BY pathname
        ORDER BY views DESC
        LIMIT {{Int32(limit, 10)}}
      `,
    }),
  ],
  output: {
    pathname: t.string(),
    views: t.uint64(),
  },
});

export type TopPagesParams = InferParams<typeof topPages>;
// { start_date: string, end_date: string, limit?: number, country?: string | undefined }

Using Parameters in SQL

When using parameters in your SQL queries, wrap them with the appropriate type function:
node({
  name: 'filtered',
  sql: `
    SELECT *
    FROM events
    WHERE timestamp >= {{DateTime(start_date)}}
      AND timestamp <= {{DateTime(end_date)}}
      AND event_name = {{String(event_type)}}
      AND user_id = {{Int32(user_id)}}
    LIMIT {{Int32(limit, 10)}}
  `,
})

Conditional Parameters

Use Jinja2 templating for optional parameters:
node({
  name: 'conditional',
  sql: `
    SELECT *
    FROM events
    WHERE timestamp >= {{DateTime(start_date)}}
      {% if defined(country) %}
      AND country = {{String(country)}}
      {% end %}
    LIMIT {{Int32(limit, 10)}}
  `,
})

Type Inference

import { type InferParams, type InferParamType } from '@tinybirdco/sdk';
import { topPages } from './pipes';

// Infer all parameters
type TopPagesParams = InferParams<typeof topPages>;
// { start_date: string, end_date: string, limit?: number }

// Infer a single parameter type
const limitValidator = p.int32().optional(10);
type LimitType = InferParamType<typeof limitValidator>; // number

Best Practices

Use Optional with Defaults

Provide sensible defaults for optional parameters to improve API usability.
limit: p.int32().optional(10)

Add Descriptions

Document your parameters for better developer experience.
start_date: p.dateTime()
  .describe('Start of date range')

Use Appropriate Types

Choose the most specific type for your use case (e.g., p.uint32() for IDs).

Validate in SQL

Add additional validation in your SQL queries when needed.

Build docs developers (and LLMs) love