This document specifies all supported query parameter types and their expected formats for URL construction and parsing.
Query parameters can be simple values, ranges, or collections. Collections can use different separators to indicate logical operations:
,
(comma) = ALL (AND condition) - all values must match|
(pipe) = ANY (OR condition) - any value can match
For complex multi-condition queries, use indexed parameters like
param[0]
, param[1]
to create separate filter groups that are
combined with OR logic.
Strive for single word keys, but otherwise use kebab-case
.
Boolean values are represented as yes
or no
.
Examples:
?active=yes
?enabled=no
?published=yes
Single integer values.
Examples:
?count=42
?age=25
?level=10
Single decimal/floating point values.
Examples:
?price=19.99
?rating=4.5
?temperature=98.6
Single string values. Spaces are encoded as +
.
Examples:
?name=john
?title=hello+world
?category=electronics
Single date values in ISO format (YYYY-MM-DD).
Examples:
?created=2025-01-15
?birthday=1990-06-20
?deadline=2025-12-31
Single datetime values in full ISO 8601 format.
Examples:
?timestamp=2025-01-15T14:30:00.000Z
?scheduled=2025-10-06T09:00:00.000Z
?updated=2025-03-20T16:45:30.500Z
Ranges support both literal values and bounded ranges with inclusive/exclusive endpoints.
Literal (exact value):
?age=25
?count=100
Inclusive range (default):
?age=18..65
?count=10..100
?level=5..n
Exclusive range:
?age=(18..65)
?count=[10..100)
?level=(5..n]
Unbounded ranges:
?age=18..n # 18 or greater
?count=n..100 # 100 or less
?level=n..n # any value
Inclusive/exclusive combinations:
?age=[18..65] # inclusive on both ends
?age=(18..65) # exclusive on both ends
?age=[18..65) # inclusive start, exclusive end
?age=(18..65] # exclusive start, inclusive end
Same format as integer ranges, but accepts decimal values.
Examples:
?price=19.99
?price=10.0..99.99
?price=(0..100.5)
?rating=4.5..5.0
?temperature=n..98.6
?score=[0.0..1.0]
Ranges of dates in ISO format.
Examples:
?created=2025-01-15
?created=2025-01-01..2025-12-31
?updated=(2025-01-01..2025-06-30)
?deadline=2025-01-01..n
?started=n..2025-12-31
Collections can contain multiple values or ranges.
Comma-separated strings where ALL values must match (AND logic).
Single value:
?tags=javascript
Multiple values (ALL must match):
?tags=javascript,typescript,node
?keywords=web,development,frontend
URL-decoded spaces:
?tags=hello+world,foo+bar
Pipe-separated strings where ANY value can match (OR logic).
Single value:
?category=electronics
Multiple values (ANY can match):
?category=electronics|clothing|books
?status=pending|active|completed
Comma-separated boolean values where ALL must match.
Examples:
?flags=yes
?flags=yes,no,yes
?enabled=yes,yes
Pipe-separated boolean values where ANY can match.
Examples:
?status=yes|no
?active=yes|yes|no
Comma-separated integers or ranges where ALL must match.
Single value:
?scores=100
Multiple values (ALL must match):
?scores=80,90,100
?levels=5,10,15
Mix of values and ranges (ALL must match):
?scores=50,60..80,90
?levels=1..5,10,15..20
With exclusive bounds:
?scores=[0..50),60,(70..100]
Pipe-separated integers or ranges where ANY can match.
Single value:
?age=25
Multiple values (ANY can match):
?age=18|25|35
?level=1|5|10
Mix of values and ranges (ANY can match):
?age=18..25|30|40..n
?level=1..5|10..15|20
Comma-separated decimals or ranges where ALL must match.
Examples:
?prices=19.99
?prices=10.0,20.5,30.99
?prices=10.0..20.0,25.5,30..40
?ratings=4.0..4.5,4.8,5.0
Pipe-separated decimals or ranges where ANY can match.
Examples:
?price=19.99|29.99|39.99
?rating=4.0..4.5|4.8..5.0
?score=0.0..0.5|0.9..1.0
?temperature=98.0..98.6|99.0..100.0
Pattern matching with wildcards for prefix, suffix, infix, or exact matches.
Wildcard patterns:
text*
= prefix match (starts with "text")*text
= suffix match (ends with "text")*text*
= infix match (contains "text")text
= exact match (equals "text")
Single pattern:
?name=john*
?email=*@example.com
?title=*world*
?code=ABC123
Multiple patterns (comma-separated):
?text=pre*,*tion,*fix*,exact
?name=john*,*smith,*doe*
?extension=*.js,*.ts,*.tsx
Multiple patterns (pipe-separated):
?filename=*.jpg|*.png|*.gif
?text=hello*|*world
Use indexed parameters [0]
, [1]
, etc. to create separate filter
groups. Groups are combined with OR logic, while properties within a
group use AND logic.
Example 1: Words matching specific criteria
Find words that are:
- (starts with "x" AND ends with "tion" AND 10+ letters AND 4+ syllables AND is noun or verb) OR
- (starts with "y" AND ends with "ed" AND 8+ letters AND is adjective)
?text[0]=x*,*tion&length[0]=10..n&syllables[0]=4..n&role[0]=noun|verb
&text[1]=y*,*ed&length[1]=8..n&role[1]=adjective
Example 2: Product filtering
Find products that are:
- (category is "electronics" AND price $100-500 AND rating 4+) OR
- (category is "books" AND price under $50)
?category[0]=electronics&price[0]=100..500&rating[0]=4..5
&category[1]=books&price[1]=n..50
Example 3: User search
Find users that are:
- (age 18-25 AND location is "NYC" or "LA") OR
- (age 30-40 AND verified)
?age[0]=18..25&location[0]=NYC|LA
&age[1]=30..40&verified[1]=yes
?param= # empty string, typically ignored
?param # no value, typically ignored
?value=n..n # any value (unbounded on both ends)
?value=10..n # 10 or greater (unbounded max)
?value=n..100 # 100 or less (unbounded min)
Collections with a single value behave the same as the basic type:
?tags=javascript # single string
?tags=javascript,typescript # collection
?age=25 # single integer
?age=25,30 # collection
?age=18,25..35,40,50..60 # ages: 18, 25-35, 40, 50-60
?price=9.99,20..50,99.99 # prices: 9.99, 20-50, 99.99
Spaces in strings are encoded as +
:
?title=hello+world
?name=john+doe+smith
Special characters are URL-encoded:
?search=foo%26bar # foo&bar
?name=caf%C3%A9 # café
When the same parameter appears multiple times in the same group, values are merged with AND logic:
?role[0]=noun&role[0]=verb # results in role: [noun, verb] with form: 'all'
- Boolean values: case-insensitive (
yes
,YES
,Yes
all work) - Unbounded marker: case-insensitive (
n
,N
both work) - String values: case-sensitive unless specified otherwise
- Property names: typically kebab-case in URLs, camelCase in code
Type | Separator | Example | Description |
---|---|---|---|
Boolean | - | ?active=yes |
yes/no values |
Integer | - | ?count=42 |
Single integer |
Decimal | - | ?price=19.99 |
Single decimal |
String | - | ?name=john |
Single string |
Date | - | ?created=2025-01-15 |
ISO date |
Datetime | - | ?updated=2025-01-15T14:30:00.000Z |
ISO datetime |
Integer Range | .. |
?age=18..65 |
Integer range or literal |
Decimal Range | .. |
?price=10.0..99.99 |
Decimal range or literal |
Date Range | .. |
?created=2025-01-01..2025-12-31 |
Date range or literal |
All String | , |
?tags=js,ts,node |
All strings must match |
Any String | | |
?category=a|b|c |
Any string can match |
All Boolean | , |
?flags=yes,no,yes |
All booleans must match |
Any Boolean | | |
?active=yes|no |
Any boolean can match |
All Integer | , |
?scores=80,90,100 |
All integers/ranges must match |
Any Integer | | |
?age=18|25|35 |
Any integer/range can match |
All Decimal | , |
?prices=10.0,20.5 |
All decimals/ranges must match |
Any Decimal | | |
?price=19.99|29.99 |
Any decimal/range can match |
String Match | , or | |
?text=pre*,*tion |
Wildcard pattern matching |
- Ranges use
n
to indicate unbounded (null) values - Bracket notation
[]
and parentheses()
control inclusive/exclusive bounds - Default range bounds are inclusive when not specified
- String match patterns use
*
as wildcard - Collections can mix literal values and ranges (for numeric/date types)
- Indexed parameters
[0]
,[1]
create OR groups - Multiple values within a group create AND conditions
- URL encoding follows standard conventions (spaces as
+
, special chars percent-encoded) - Query parameter keys should strive for single-word terms when
possible, otherwise use kebab-case (e.g.,
created-at
,user-id
)