Dates (date_range)
A calendar for choosing one date or a date range (stays, appointments, deadlines).
When to use it: The person picks a date, or a check-in and check-out range, on a calendar with limits and unavailable days.
When not to use it: Do not use it when you already have specific times or a few fixed options to offer (use time_slots), or for a single date the person can just type in chat.
Gather first:
- Whether you need one date (
mode: "single") or a stay from start to end ("range"). - The earliest and latest dates you can work with, and any dates that are not possible.
Writing good content:
- Set
minDateandmaxDateto the real window and list impossible days indisabledDates, so the person cannot pick a date you cannot use. - For stays, set
minNightsandmaxNightswhen the place requires them. For any other period (a trip, time off, a deadline window) setstay: false, so the page does not count nights. - Use
dayNotesfor a very short note under a day, such as a nightly price, only when you have it for those days.
Fields
Every page also has version (always 1), title, and optionally description, branding, cover (a header photo) and expiresAt; see Page fields. These are the fields of page (the page type and its data):
| Field | Description |
|---|---|
mode | "single" | "range", required. "single" picks one date; "range" picks a start and an end date. |
minDate | string. Earliest selectable date. Days before it are disabled. Defaults to no limit. |
maxDate | string. Latest selectable date. Days after it are disabled. Defaults to no limit. |
disabledDates | string[]. Dates that cannot be chosen, e.g. days with no availability. A range cannot span a disabled date. Limits: at most 400 items. |
minNights | integer. Range mode only: fewest nights (endDate minus startDate). Defaults to 1. Limits: 1-365. |
maxNights | integer. Range mode only: most nights. Defaults to no limit. Limits: 1-365. |
stay | boolean. Range mode only. Omit or true for a stay (check-in to check-out): the page counts and shows nights. false for any other period (a trip, time off, a deadline window): no night count, and minNights/maxNights read as days between the dates. |
dayNotes | object[]. Optional small note per date, usually a price, e.g. { "date": "2026-11-03", "note": "$129" }. Limits: at most 400 items. |
dayNotes[].date | string, required. Calendar date as "YYYY-MM-DD", e.g. "2026-11-03". No time or time zone. |
dayNotes[].note | string, required. Very short text under the day number, e.g. "$129". Max 8 characters. Limits: 1-8 characters. |
defaultValue | object. Optional preselected answer. Use { date } in single mode or { startDate, endDate } in range mode. |
defaultValue (variant 1).date | string, required. The chosen date, "YYYY-MM-DD". |
defaultValue (variant 2).startDate | string, required. First day of the range (check-in), "YYYY-MM-DD". |
defaultValue (variant 2).endDate | string, required. Last day of the range (check-out), "YYYY-MM-DD". Nights = endDate minus startDate. |
Why these are required: It decides the result shape ({ date } or { startDate, endDate }).
When optional fields are left out: No limits; at least 1 night in range mode; a range is a stay and the page counts nights (stay: false drops the night count for other periods); nothing preselected.
Minimal example
Only the required fields:
{
"version": 1,
"title": "When should the piano tuner come?",
"page": {
"type": "date_range",
"mode": "single"
}
}Full example
{
"version": 1,
"title": "Pick your dates at Harbor Light Inn",
"description": "Nightly rates are shown under each day. Stays are 2 to 7 nights.",
"branding": {
"name": "Juniper Concierge",
"accentColor": "#0050d8"
},
"page": {
"type": "date_range",
"mode": "range",
"minDate": "2026-11-02",
"maxDate": "2027-01-31",
"minNights": 2,
"maxNights": 7,
"disabledDates": [
"2026-11-12",
"2026-11-13",
"2026-11-27"
],
"dayNotes": [
{
"date": "2026-11-03",
"note": "$129"
},
{
"date": "2026-11-04",
"note": "$129"
},
{
"date": "2026-11-05",
"note": "$139"
},
{
"date": "2026-11-06",
"note": "$159"
},
{
"date": "2026-11-07",
"note": "$189"
},
{
"date": "2026-11-08",
"note": "$189"
},
{
"date": "2026-11-09",
"note": "$149"
},
{
"date": "2026-11-10",
"note": "$129"
},
{
"date": "2026-11-11",
"note": "$129"
},
{
"date": "2026-11-12",
"note": "$135"
},
{
"date": "2026-11-13",
"note": "$155"
},
{
"date": "2026-11-14",
"note": "$185"
},
{
"date": "2026-11-15",
"note": "$189"
},
{
"date": "2026-11-16",
"note": "$149"
},
{
"date": "2026-11-17",
"note": "$129"
},
{
"date": "2026-11-18",
"note": "$129"
},
{
"date": "2026-11-19",
"note": "$129"
},
{
"date": "2026-11-20",
"note": "$139"
}
]
}
}Result
When the person submits, the result has these fields:
| Field | Description |
|---|---|
(variant 1).date | string, required. The chosen date, "YYYY-MM-DD". |
(variant 2).startDate | string, required. First day of the range (check-in), "YYYY-MM-DD". |
(variant 2).endDate | string, required. Last day of the range (check-out), "YYYY-MM-DD". Nights = endDate minus startDate. |
For the full example above, a result could be:
{
"startDate": "2026-11-03",
"endDate": "2026-11-06"
}Send it
eve, AI SDK and MCP
With @pagesystems/eve, @pagesystems/ai-sdk or the MCP server, the model calls get_page_type_schema with "date_range" (the same JSON as GET /v1/page-types/date_range), then create_page with this input (no version or branding; branding comes from your dashboard):
{
"title": "Pick your dates at Harbor Light Inn",
"description": "Nightly rates are shown under each day. Stays are 2 to 7 nights.",
"page": {
"type": "date_range",
"mode": "range",
"minDate": "2026-11-02",
"maxDate": "2027-01-31",
"minNights": 2,
"maxNights": 7,
"disabledDates": [
"2026-11-12",
"2026-11-13",
"2026-11-27"
],
"dayNotes": [
{
"date": "2026-11-03",
"note": "$129"
},
{
"date": "2026-11-04",
"note": "$129"
},
{
"date": "2026-11-05",
"note": "$139"
},
{
"date": "2026-11-06",
"note": "$159"
},
{
"date": "2026-11-07",
"note": "$189"
},
{
"date": "2026-11-08",
"note": "$189"
},
{
"date": "2026-11-09",
"note": "$149"
},
{
"date": "2026-11-10",
"note": "$129"
},
{
"date": "2026-11-11",
"note": "$129"
},
{
"date": "2026-11-12",
"note": "$135"
},
{
"date": "2026-11-13",
"note": "$155"
},
{
"date": "2026-11-14",
"note": "$185"
},
{
"date": "2026-11-15",
"note": "$189"
},
{
"date": "2026-11-16",
"note": "$149"
},
{
"date": "2026-11-17",
"note": "$129"
},
{
"date": "2026-11-18",
"note": "$129"
},
{
"date": "2026-11-19",
"note": "$129"
},
{
"date": "2026-11-20",
"note": "$139"
}
]
}
}REST
curl https://pagesystems.ai/v1/pages \
-H "Authorization: Bearer $PAGE_SYSTEMS_API_KEY" \
-H "Content-Type: application/json" \
-d '{"spec":{"version":1,"title":"Pick your dates at Harbor Light Inn","description":"Nightly rates are shown under each day. Stays are 2 to 7 nights.","branding":{"name":"Juniper Concierge","accentColor":"#0050d8"},"page":{"type":"date_range","mode":"range","minDate":"2026-11-02","maxDate":"2027-01-31","minNights":2,"maxNights":7,"disabledDates":["2026-11-12","2026-11-13","2026-11-27"],"dayNotes":[{"date":"2026-11-03","note":"$129"},{"date":"2026-11-04","note":"$129"},{"date":"2026-11-05","note":"$139"},{"date":"2026-11-06","note":"$159"},{"date":"2026-11-07","note":"$189"},{"date":"2026-11-08","note":"$189"},{"date":"2026-11-09","note":"$149"},{"date":"2026-11-10","note":"$129"},{"date":"2026-11-11","note":"$129"},{"date":"2026-11-12","note":"$135"},{"date":"2026-11-13","note":"$155"},{"date":"2026-11-14","note":"$185"},{"date":"2026-11-15","note":"$189"},{"date":"2026-11-16","note":"$149"},{"date":"2026-11-17","note":"$129"},{"date":"2026-11-18","note":"$129"},{"date":"2026-11-19","note":"$129"},{"date":"2026-11-20","note":"$139"}]}}}'Validation errors
A spec that does not validate is refused with 400 invalid_spec. The message names each problem and its path, so a model can fix the spec and try again. For example:
Leaving out the required field mode:
✖ Invalid option: expected one of "single"|"range"
→ at page.modeMisspelling a field name (unknown keys are rejected):
✖ Unrecognized key: "colour"
→ at page