Skip to content

Instantly share code, notes, and snippets.

@lancejpollard
Last active October 6, 2025 22:37
Show Gist options
  • Save lancejpollard/c50bd1bfc4c7fdf94c3c94dead0fb67a to your computer and use it in GitHub Desktop.
Save lancejpollard/c50bd1bfc4c7fdf94c3c94dead0fb67a to your computer and use it in GitHub Desktop.
URL Query Param Spec

URL Query Param Spec

This document specifies all supported query parameter types and their expected formats for URL construction and parsing.

Overview

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.

Basic Query Param Types

Boolean Query Params

Boolean values are represented as yes or no.

Examples:

?active=yes
?enabled=no
?published=yes

Integer Query Params

Single integer values.

Examples:

?count=42
?age=25
?level=10

Decimal Query Params

Single decimal/floating point values.

Examples:

?price=19.99
?rating=4.5
?temperature=98.6

String Query Params

Single string values. Spaces are encoded as +.

Examples:

?name=john
?title=hello+world
?category=electronics

Date Query Params

Single date values in ISO format (YYYY-MM-DD).

Examples:

?created=2025-01-15
?birthday=1990-06-20
?deadline=2025-12-31

Datetime Query Params

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

Range Query Param Types

Ranges support both literal values and bounded ranges with inclusive/exclusive endpoints.

Integer Range Query Params

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

Decimal Range Query Params

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]

Date Range Query Params

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

Collection Query Param Types

Collections can contain multiple values or ranges.

All String Query Params

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

Any String Query Params

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

All Boolean Query Params

Comma-separated boolean values where ALL must match.

Examples:

?flags=yes
?flags=yes,no,yes
?enabled=yes,yes

Any Boolean Query Params

Pipe-separated boolean values where ANY can match.

Examples:

?status=yes|no
?active=yes|yes|no

All Integer Query Params

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]

Any Integer Query Params

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

All Decimal Query Params

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

Any Decimal Query Params

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

String Match Query Params

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

Complex Multi-Condition Queries

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

Edge Cases and Special Scenarios

Empty or Null Values

?param=         # empty string, typically ignored
?param          # no value, typically ignored

Unbounded Ranges

?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)

Single Item Collections

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

Mixing Literals and Ranges in Collections

?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

URL Encoding

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é

Multiple Same Parameters in Same Group

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'

Case Sensitivity

  • 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

Summary Table

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

Implementation Notes

  • 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)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment