upsert_spots
Create or update up to 25 spots by your own ref.
/v1/guides/{productId}/spots/batchBulk and idempotent: each item is a create_spot body plus a required ref (your stable key). A spot of this guide with that ref is updated with the fields you send; any other ref creates a spot. One transaction per call, so one bad item rejects the batch and nothing half-lands; the error names the ref. Returns [{ ref, spotId, spotKey, created }] and any warnings, with status 201 even when every item was an update. Re-running the same batch never duplicates spots.
curl -X POST "https://sceniq.earth/api/v1/guides/j5738kd1q9x2m7v4c6b8n0p3r5t1w9y2/spots/batch" \
-H "Authorization: Bearer $SCENIQ_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"spots": [
{
"ref": "yose-tunnel-view",
"title": "Tunnel View",
"kicker": "Yosemite Valley",
"lat": 37.7156,
"lon": -119.677,
"mapsUrl": "https://www.google.com/maps/search/?api=1&query=37.7156,-119.677",
"shortDescription": "El Capitan, Half Dome and Bridalveil Fall in one frame, at the east end of the Wawona Tunnel.",
"accessMode": "drive_up",
"customValues": {
"best_time": "sunset",
"crowds": "busy"
}
},
{
"ref": "yose-glacier-point",
"title": "Glacier Point",
"kicker": "Yosemite, above the valley",
"lat": 37.7307,
"lon": -119.5741,
"shortDescription": "Half Dome, Vernal Fall and Nevada Fall from nearly 1,000 meters above the valley floor.",
"accessMode": "drive_up",
"customValues": {
"best_time": "sunset",
"crowds": "packed"
}
},
{
"ref": "yose-taft-point",
"title": "Taft Point",
"kicker": "Yosemite, Glacier Point Road",
"lat": 37.7125,
"lon": -119.6049,
"shortDescription": "Fissures in the granite and a sheer drop to the valley, with El Capitan across the gap.",
"accessMode": "hike",
"customValues": {
"best_time": "sunset",
"crowds": "busy"
}
}
]
}'Path parameters
- productIdstring · guide idrequired
Id of the guide (a product of type map). From
list_guidesorcreate_guide.
Body parameters
- spotsarray of objectsrequired
Up to 25 items: every
create_spotfield plus ref (required).Show 35 fieldsHide fields
- titlestringrequired
Place name as locals know it, e.g. Oeschinensee or Fushimi Inari-taisha. Cannot be empty.
- kickerstringoptional
Short eyebrow above the title, e.g. Patagonia, Bernese Oberland or Glacier lake. Empty string clears.
- latnumberoptional
Latitude in decimal degrees (-90 to 90). From the creator's material or a cited source.
- lonnumberoptional
Longitude in decimal degrees (-180 to 180).
- mapsUrlstringoptional
The creator's own map link: https on Google Maps, Apple Maps, Swisstopo, OpenStreetMap or SchweizMobil, or a geo: URI. Empty string clears.
- shortDescriptionstringoptional
One or two sentences for the card. Empty string clears.
- longDescriptionstringoptional
The full write-up in the creator's voice. Empty string clears.
- colorstringoptional
Optional pin color hex, e.g. #0071e3. Empty string clears.
- cardOrientationstringoptional
portrait or landscape (photo framing in the viewer); a spot without one reads as landscape.
portraitlandscape - customValuesmap of valuesoptional
Object keyed by property key (
list_properties): text forshortLabelandlongSection, a number for number, epoch ms for date, one option id forsingleSelect, an array of option ids for checkbox (ids, never labels). Every required property needs a value; keys without a live property are kept unchecked. Sent for an existing spot it replaces the stored object; null for a key clears that value. How to get there, full replacement, null clears: {
byCar?: { directions, parking,walkToSpotMin,walkRoundTrip? (the minutes are there and back), none? (no car access), note? },byTrainBus?: { route,walkFromStopMin,walkRoundTrip?, none? (no public transport, which reads differently from an empty field), note? },byBoat?,byAir?: { airports? (IATA or ICAO codes), route?, minutes?,operatorUrl?,luggageKg?, none?, note? },onFoot?: { route?, minutes?,roundTrip?, none?, note? },byBike?: { same },bestTime?, operating?, approaches?: [{ label (Argentine side), country? (AR), legs?: [{ mode: car|bus|train|tram|metro|cable_car|funicular|boat|ferry|plane|helicopter|shuttle|jeep|walk|bike|taxi|other, from?, to?, minutes?,roundTrip?, price?, payment?, note? }], hours?, entry?, note?, lat?, lon? }] (at most 6, for spots with several ways in or chains of legs), rules?: [{ text, kind?: reservation|permit|guide|registration|no_independent_travel|vehicle|other, months? [1-12] (shown only then),appliesTo?: car|all,bookingOpens?,sourceUrl? }] }.Show 10 fieldsHide fieldsof Arrival
- byCarobjectoptional
Driving and parking.
Show 6 fieldsHide fields
- directionsstringoptional
The drive in words, at most 2,000 characters.
- parkingstringoptional
Where to park, at most 1,000 characters.
- walkToSpotMinnumberoptional
Minutes on foot from the car to the spot.
- walkRoundTripbooleanoptional
true when
walkToSpotMinis there and back. - nonebooleanoptional
true when the spot has no car access.
- notestringoptional
One more line about driving, at most 500 characters.
- byTrainBusobjectoptional
Public transport.
Show 5 fieldsHide fields
- routestringoptional
The connection in words, at most 2,000 characters.
- walkFromStopMinnumberoptional
Minutes on foot from the stop to the spot.
- walkRoundTripbooleanoptional
true when
walkFromStopMinis there and back. - nonebooleanoptional
true when there is no public transport.
- notestringoptional
One more line about public transport, at most 500 characters.
- byBoatstringoptional
The boat connection in words, at most 2,000 characters.
- byAirobjectoptional
Flights or helicopter.
Show 7 fieldsHide fields
- airportsarray of stringsoptional
Up to 8 IATA or ICAO codes (LUA, VNLK).
- routestringoptional
The flight in words, at most 2,000 characters.
- minutesnumberoptional
Flight time in minutes.
- operatorUrlstringoptional
The operator's page (http or https).
- luggageKgnumberoptional
The luggage limit in kilograms (1 to 200).
- nonebooleanoptional
true when there is no air access.
- notestringoptional
One more line about flying, at most 500 characters.
Walking in.
Show 5 fieldsHide fieldsof ArrivalModeBlock
- routestringoptional
The way in words, at most 2,000 characters.
- minutesnumberoptional
Minutes it takes.
- roundTripbooleanoptional
true when minutes is there and back.
- nonebooleanoptional
true when this mode is not possible.
- notestringoptional
One more line, at most 500 characters.
Cycling in.
Show 5 fieldsHide fieldsof ArrivalModeBlock
- routestringoptional
The way in words, at most 2,000 characters.
- minutesnumberoptional
Minutes it takes.
- roundTripbooleanoptional
true when minutes is there and back.
- nonebooleanoptional
true when this mode is not possible.
- notestringoptional
One more line, at most 500 characters.
- bestTimestringoptional
The best time to go in words, at most 1,000 characters.
- operatingstringoptional
When the access runs (seasons, hours of a road or a ferry), at most 2,000 characters.
- approachesarray of objectsoptional
Up to 6 ways in, for spots with several approaches or chains of legs (a flight, then a jeep, then a walk).
Show 8 fieldsHide fields
- labelstringrequired
The approach's name, at most 80 characters (Argentine side).
- countrystringoptional
ISO 3166-1 alpha-2 code of the country it starts in (AR).
- legsarray of objectsoptional
Up to 12 legs in order.
Show 8 fieldsHide fields
- modestringrequired
car, bus, train, tram, metro,
cable_car, funicular, boat, ferry, plane, helicopter, shuttle, jeep, walk, bike, taxi or other.carbustraintrammetrocable_carfunicularboatferryplanehelicoptershuttlejeepwalkbiketaxiother - fromstringoptional
Where the leg starts, at most 120 characters.
- tostringoptional
Where the leg ends, at most 120 characters.
- minutesnumberoptional
Minutes the leg takes.
- roundTripbooleanoptional
true when minutes is there and back.
- pricestringoptional
The leg's price in words, at most 80 characters.
- paymentstringoptional
How the leg is paid, at most 80 characters.
- notestringoptional
One line for the leg, at most 300 characters.
- hoursstringoptional
When the approach runs, at most 300 characters.
- entrystringoptional
What entry takes on this side, at most 300 characters.
- notestringoptional
One more line, at most 500 characters.
- latnumberoptional
Latitude of the approach's start.
- lonnumberoptional
Longitude of the approach's start.
Up to 20 access rules (reservations, permits), each shown in its months.
Show 6 fieldsHide fieldsof AccessRule
- textstringrequired
The rule in the creator's words, at most 300 characters.
- kindstringoptional
reservation, permit, guide, registration,
no_independent_travel, vehicle or other.reservationpermitguideregistrationno_independent_travelvehicleother - monthsarray of numbersoptional
The months the rule applies (1 to 12); the apps show it only then. Absent means all year.
- appliesTostringoptional
car for a rule that only binds drivers (a timed entry for vehicles), all for everyone.
carall - bookingOpensstringoptional
When booking opens, in words, at most 100 characters (90 days ahead at 07:00).
- sourceUrlstringoptional
The page that states the rule (http or https).
Extra map links [{ label, url }] (https or an allowlisted map link), drawn as map pills. [] clears. For official, ticket or status pages use links instead.
Show 2 fieldsHide fieldsof MapLink
- labelstringrequired
The pill text, at most 40 characters.
- urlstringrequired
An https page or an allowlisted map link.
- imagesEnabledbooleanoptional
false hides the photo section from buyers; photos stay stored.
- customPropsEnabledbooleanoptional
false hides custom properties from buyers; values stay stored.
The planning stats bar, null clears: {
elevationM? (meters; 0 is a stated sea level, absent is unknown),elevationRefersTo?: viewpoint|summit|ground|water|trailhead,elevationSource?, busyness? (1 quiet to 5 packed, shown as Crowdedness),bestSeason? }.Show 5 fieldsHide fieldsof TripFacts
- elevationMnumberoptional
Elevation in meters (-500 to 9,000). 0 is a stated sea level; absent is unknown.
- elevationRefersTostringoptional
What the elevation measures: viewpoint, summit, ground, water or trailhead.
viewpointsummitgroundwatertrailhead - elevationSourcestringoptional
Where the number comes from, at most 300 characters.
- busynessnumberoptional
Crowds from 1 (quiet) to 5 (packed), shown as Crowdedness.
- bestSeasonstringoptional
The best season in words, at most 200 characters.
- accessModestring or nulloptional
How visitors reach the spot, shown as Accessibility:
drive_up,short_walk, hike,multi_day, boat,cable_car, train, flight,tour_only,aerial_only. null clears. Without it the cell shows the easiest required route's grade, or Drive-up only when arrival.byCardescribes a drive.drive_upshort_walkhikemulti_dayboatcable_cartrainflighttour_onlyaerial_only - pinLabelstringoptional
What the main pin marks for a spot that is an area or a line, shown as Pinned: <label> (Ti Top viewpoint). Empty string clears.
Extra points, full replacement ([] clears), at most 12: [{ kind: viewpoint|entrance|gate|trailhead|parking|stop|pier|summit|other, label, lat, lon, months? [1-12] (only reachable then), note? }]. Each gets its own map links and a place on the web map.
Show 6 fieldsHide fieldsof SpotPin
- kindstringrequired
viewpoint, entrance, gate, trailhead, parking, stop, pier, summit or other.
viewpointentrancegatetrailheadparkingstoppiersummitother - labelstringrequired
What buyers read next to the pin, at most 80 characters (South rim viewpoint).
- latnumberrequired
Latitude in decimal degrees (-90 to 90), from the creator's material or a cited source.
- lonnumberrequired
Longitude in decimal degrees (-180 to 180).
- monthsarray of numbersoptional
The months the point is reachable (1 to 12). Absent means all year.
- notestringoptional
One line of context, at most 300 characters.
Links with a purpose, full replacement ([] clears), at most 12: [{ kind: official|website|tickets|booking|status|timetable|tide|listing|social|authority|app|other, label?, url? (http or https; http is accepted with a warning), value? (a channel that is not a URL, e.g. WeChat mini program: Li River boats), note? }]. Each needs a url or a value.
Show 5 fieldsHide fieldsof GuideLink
- kindstringrequired
What the link is for. official and website are the place's own pages; tickets and booking sell entry or rooms; status, timetable and tide carry live conditions; listing, social, authority and app cover the rest.
officialwebsiteticketsbookingstatustimetabletidelistingsocialauthorityappother - labelstringoptional
The link text buyers see, at most 60 characters. Without it the apps name the link by its kind.
- urlstringoptional
An http or https page. http is accepted with a warning.
- valuestringoptional
A channel that is not a URL, at most 200 characters, for example a WeChat mini program and its search term.
- notestringoptional
One line of context shown under the link, at most 300 characters.
Closure or works notice, null clears: { state: open|
partly_closed|closed|reopening, note?, since?, until? (the day the state is expected to end; buyers stop seeing the notice after it),sourceUrl?,checkedOn? }. reopening with until means reopens on that day.Show 6 fieldsHide fieldsof StatusNotice
- statestringrequired
open,
partly_closed, closed or reopening. reopening with until means it reopens on that day.openpartly_closedclosedreopening - notestringoptional
What is closed or changed, in the creator's words, at most 500 characters.
- sincestringoptional
The day the state began (YYYY-MM-DD).
- untilstringoptional
The day the state is expected to end (YYYY-MM-DD). Must not be before since.
- sourceUrlstringoptional
The page that announced it (http or https).
- checkedOnstringoptional
The day the value was last checked against its source (YYYY-MM-DD).
Fees and tickets, full replacement ([] clears), at most 30: [{ label, amount? (major units, e.g. 40 or 12.5; needs currency), currency? (EUR), free?,
seeOfficial? (a price left to the official page on purpose), per?: person|vehicle|night|group|entry|day|hour, audience?: all|adult|child|foreign|domestic|resident|student|senior,paidWhere?: online|on_site|in_tour, payment?:cash_only|card_only|cash_or_card, note?,validFrom?,validUntil?,sourceUrl?,checkedOn? }]. Buyers see the amount with an as-of date; readiness flags rows pastvalidUntilor unchecked for a year.Show 14 fieldsHide fieldsof Fee
- labelstringrequired
What the fee is for, at most 80 characters (Adult entry, Car park, Boat transfer).
- amountnumberoptional
The price in major units (40, 12.5). Needs currency. Absent when the fee is free or left to the official page.
- currencystringoptional
ISO 4217 code (USD, EUR, ARS). Required with amount.
- freebooleanoptional
true for no charge. Cannot be combined with an amount.
- seeOfficialbooleanoptional
true for a price the guide leaves to the official page on purpose (it changes too often to copy).
- perstringoptional
What one amount pays for: person, vehicle, night, group, entry, day or hour.
personvehiclenightgroupentrydayhour - audiencestringoptional
Who pays this rate: all, adult, child, foreign, domestic, resident, student or senior.
alladultchildforeigndomesticresidentstudentsenior - paidWherestringoptional
Where it is paid: online,
on_siteorin_tour(part of a tour price).onlineon_sitein_tour - paymentstringoptional
How it can be paid:
cash_only,card_onlyorcash_or_card.cash_onlycard_onlycash_or_card - notestringoptional
One line of context, at most 300 characters (free on the first Sunday of the month).
- validFromstringoptional
The first day the price applies (YYYY-MM-DD).
- validUntilstringoptional
The last day the price applies (YYYY-MM-DD). Readiness flags the row after it.
- sourceUrlstringoptional
The page the price comes from (http or https).
- checkedOnstringoptional
The day the value was last checked against its source (YYYY-MM-DD).
Structured opening hours, null clears; the free-text hours stay the fallback: { hours?: [{ from? (MM-DD), to? (MM-DD, may wrap over the new year), weekdays? [1-7], closed?, open? (HH:MM or sunrise|sunset), close? (HH:MM or sunrise|sunset),
openOffsetMin?,closeOffsetMin? (minutes around a sun anchor, -60 = an hour before),lastEntry? (HH:MM),leaveBy? (HH:MM), note? }],specialDays?: [{ date? or rule? (first Sunday of the month), closed?, open?, close?, note? }], slots?: { first, last,everyMin, cap?, note? },validFrom?,validUntil?,sourceUrl?,checkedOn?, note? }. The last matching band wins, so list the year-round band first and exceptions after it. The apps show today's hours in the spot's time zone.Show 8 fieldsHide fieldsof Schedule
Up to 24 bands; the last matching band wins.
Show 11 fieldsHide fieldsof HoursBand
- fromstringoptional
First day of the band as MM-DD. Absent means the start of the year.
- tostringoptional
Last day of the band as MM-DD. May wrap over the new year (from 11-01 to 03-31).
- weekdaysarray of numbersoptional
The weekdays it covers, 1 (Monday) to 7 (Sunday). Absent means every day.
- closedbooleanoptional
true when the place is closed in this band. Otherwise open and close are required.
- openstringoptional
Opening time as HH:MM, or sunrise or sunset.
- closestringoptional
Closing time as HH:MM, or sunrise or sunset.
- openOffsetMinnumberoptional
Minutes around a sun anchor for open (-240 to 240; -60 is an hour before sunrise).
- closeOffsetMinnumberoptional
Minutes around a sun anchor for close (-240 to 240).
- lastEntrystringoptional
Last entry as HH:MM.
- leaveBystringoptional
The time visitors must be out as HH:MM.
- notestringoptional
One line for the band, at most 200 characters.
- specialDaysarray of objectsoptional
Up to 40 days that differ from the bands: a date or a rule, closed or with their own times.
Show 6 fieldsHide fields
- datestringoptional
The day (YYYY-MM-DD). Give a date or a rule.
- rulestringoptional
A recurring day in words, at most 120 characters (first Sunday of the month).
- closedbooleanoptional
true when the place is closed that day.
- openstringoptional
Opening time that day as HH:MM, or sunrise or sunset.
- closestringoptional
Closing time that day as HH:MM, or sunrise or sunset.
- notestringoptional
One line for the day, at most 200 characters.
- slotsobjectoptional
Timed entry: entries every
everyMinminutes from first to last.Show 5 fieldsHide fields
- firststringrequired
The first entry time as HH:MM.
- laststringrequired
The last entry time as HH:MM.
- everyMinnumberrequired
Minutes between entries.
- capnumberoptional
People per slot, when the source states it (1 to 100,000).
- notestringoptional
One line about booking a slot, at most 200 characters.
- validFromstringoptional
The first day these hours apply (YYYY-MM-DD).
- validUntilstringoptional
The last day these hours apply (YYYY-MM-DD).
- sourceUrlstringoptional
The page the hours come from (http or https).
- checkedOnstringoptional
The day the value was last checked against its source (YYYY-MM-DD).
- notestringoptional
A note for the whole schedule, at most 500 characters.
Parts of the site with their own rules (a monastery's closing day, a ticketed skyway), full replacement, at most 12: [{ name, note?, hours?, entry?, season?, fees? (as fees), status? (as status), url? }].
Show 8 fieldsHide fieldsof SpotFeature
- namestringrequired
The part's name, at most 80 characters.
- notestringoptional
What to know about it, at most 500 characters.
- hoursstringoptional
Its hours in words, at most 200 characters.
- entrystringoptional
Its entry rule or price in words, at most 200 characters.
- seasonstringoptional
When it is open in words, at most 200 characters.
Its own fees, as the spot's fees.
Show 14 fieldsHide fieldsof Fee
- labelstringrequired
What the fee is for, at most 80 characters (Adult entry, Car park, Boat transfer).
- amountnumberoptional
The price in major units (40, 12.5). Needs currency. Absent when the fee is free or left to the official page.
- currencystringoptional
ISO 4217 code (USD, EUR, ARS). Required with amount.
- freebooleanoptional
true for no charge. Cannot be combined with an amount.
- seeOfficialbooleanoptional
true for a price the guide leaves to the official page on purpose (it changes too often to copy).
- perstringoptional
What one amount pays for: person, vehicle, night, group, entry, day or hour.
personvehiclenightgroupentrydayhour - audiencestringoptional
Who pays this rate: all, adult, child, foreign, domestic, resident, student or senior.
alladultchildforeigndomesticresidentstudentsenior - paidWherestringoptional
Where it is paid: online,
on_siteorin_tour(part of a tour price).onlineon_sitein_tour - paymentstringoptional
How it can be paid:
cash_only,card_onlyorcash_or_card.cash_onlycard_onlycash_or_card - notestringoptional
One line of context, at most 300 characters (free on the first Sunday of the month).
- validFromstringoptional
The first day the price applies (YYYY-MM-DD).
- validUntilstringoptional
The last day the price applies (YYYY-MM-DD). Readiness flags the row after it.
- sourceUrlstringoptional
The page the price comes from (http or https).
- checkedOnstringoptional
The day the value was last checked against its source (YYYY-MM-DD).
Its own closure notice.
Show 6 fieldsHide fieldsof StatusNotice
- statestringrequired
open,
partly_closed, closed or reopening. reopening with until means it reopens on that day.openpartly_closedclosedreopening - notestringoptional
What is closed or changed, in the creator's words, at most 500 characters.
- sincestringoptional
The day the state began (YYYY-MM-DD).
- untilstringoptional
The day the state is expected to end (YYYY-MM-DD). Must not be before since.
- sourceUrlstringoptional
The page that announced it (http or https).
- checkedOnstringoptional
The day the value was last checked against its source (YYYY-MM-DD).
- urlstringoptional
Its own page (http or https).
Rules on site, full replacement, at most 20: [{ kind:
no_photo|wide_only|no_drone|no_entry|no_stopping|no_parking|other, label, note?, lat?, lon?,radiusM?, line? ([[lon, lat], ...] for a stretch of road),sourceUrl? }].Show 8 fieldsHide fieldsof Restriction
- kindstringrequired
no_photo,wide_only(shown as Wide shots only),no_drone,no_entry,no_stopping,no_parkingor other.no_photowide_onlyno_droneno_entryno_stoppingno_parkingother - labelstringrequired
The rule as buyers read it, at most 80 characters.
- notestringoptional
More context, at most 300 characters.
- latnumberoptional
Latitude of the point the rule applies around.
- lonnumberoptional
Longitude of the point the rule applies around.
- radiusMnumberoptional
The radius around lat and lon in meters (1 to 100,000).
- linearray of array of numbersoptional
A stretch of road or trail instead of a point: 2 to 200 [lon, lat] positions.
- sourceUrlstringoptional
The page that states the rule (http or https).
Recurring or one-off events worth timing a visit for, full replacement, at most 12: [{ name, when (in words: every night at 19:45 and 20:45), dates? [YYYY-MM-DD] (the apps show the next one), months?, url?, free?, note? }].
Show 7 fieldsHide fieldsof SpotEvent
- namestringrequired
The event's name, at most 80 characters.
- whenstringrequired
When, in words, at most 200 characters (every night at 19:45 and 20:45).
- datesarray of stringsoptional
Exact dates when known (YYYY-MM-DD, up to 60). Readiness lists events whose dates have all passed.
- monthsarray of numbersoptional
The months it happens (1 to 12).
- urlstringoptional
The event's page (http or https).
- freebooleanoptional
true when it costs nothing to watch.
- notestringoptional
One line of context, at most 300 characters.
Why the spot lists no food places, null clears: { status: included (meals come with the lodge or boat) |
none_nearby|bring_your_own, note? }.Show 2 fieldsHide fieldsof FoodNote
- statusstringrequired
included (meals come with the lodge or boat),
none_nearby, orbring_your_own.includednone_nearbybring_your_own - notestringoptional
One line of context, at most 300 characters.
- areaIdstringoptional
The area (park, island, region) the spot sits in, from
set_area; its rules, fees and links show on the spot. Empty string clears. - timeZonestringoptional
IANA zone (America/Phoenix). Derived from the pin on every write; set it only when the lookup is wrong near a border. Empty string hands it back to the pin.
- customNotesmap of stringsoptional
One short note per custom property value, keyed by property key, shown next to the value (walls 40 EUR, morning from viewpoint 7). Full replacement ({} clears).
Research evidence for reviewers, never shown to buyers; full replacement, at most 40: [{ url? or title?, kind?: page|api|archive|document|other,
capturedOn?, note?, supports? (which facts it backs, e.g. fees, arrival.operating, lat/lon), conflict? (true when it disagrees with another source on those facts) }].Show 7 fieldsHide fieldsof SourceRef
- urlstringoptional
The page, API or archive copy the facts come from (http or https).
- titlestringoptional
A name for a source without a URL (a park leaflet, a phone call with the operator), at most 200 characters.
- kindstringoptional
page, api, archive, document or other.
pageapiarchivedocumentother - capturedOnstringoptional
The day the source was read (YYYY-MM-DD).
- notestringoptional
What the source says or why it was chosen, at most 500 characters.
- supportsarray of stringsoptional
Which facts it backs, up to 12 entries of at most 60 characters (fees, arrival.operating, lat/lon).
- conflictbooleanoptional
true when this source disagrees with another on the facts it backs. Say which one the value follows in note or
reviewNotes.
- reviewNotesstringoptional
Notes for the creator's review (why a value was chosen, what could not be verified). Never shown to buyers;
get_guide_readinesslists them. Empty string clears. - factsCheckedOnstringoptional
The day the facts were last checked against their sources (YYYY-MM-DD). Empty string clears.
- reviewBystringoptional
The day the facts need a new check (YYYY-MM-DD), e.g. when a season, fare or timetable runs out.
get_guide_readinessandget_publish_statuswarn once it has passed. Empty string clears. The day something at the spot changed (a bridge replaced, boats banned), null clears: { on (YYYY-MM-DD), note? }. Readiness flags photos captured before it.
Show 2 fieldsHide fieldsof SiteChange
- onstringrequired
The day of the change (YYYY-MM-DD). Required.
- notestringoptional
What changed, at most 300 characters.
- refstringrequired
Required: your own stable key for the spot, 1 to 80 characters (letters, digits, dot, underscore, colon or hyphen, a letter or digit first), once per batch. A spot of this guide with that ref is updated with the fields sent; any other ref creates a spot.
Returns
201 Created with this object.
- productIdstring · guide idrequired
The guide's id.
- creatednumberrequired
Spots created.
- updatednumberrequired
Spots updated.
- resultsarray of objectsrequired
One result per item, in order.
Show 4 fieldsHide fields
- refstringrequired
Your ref.
- spotIdstring · spot idrequired
The spot's id.
- spotKeystringrequired
The spot's key.
- createdbooleanrequired
true when this call created the spot.
- warningsarray of stringsoptional
Notes about things the write accepted but you should look at (a plain http link). Present only when there are any.
{
"productId": "j5738kd1q9x2m7v4c6b8n0p3r5t1w9y2",
"created": 3,
"updated": 0,
"results": [
{
"ref": "yose-tunnel-view",
"spotId": "k17bc3xz8h6f4d2s0q9w7e5r3t1y2v4j",
"spotKey": "01M2Z1G0Y0R2K5P8S1V4X7Z0C3",
"created": true
},
{
"ref": "yose-glacier-point",
"spotId": "k1736b344br1c7m8qk8ks4sfndxyyftj",
"spotKey": "01M3H2AWH0F9PB64V7QB8QS0MC",
"created": true
},
{
"ref": "yose-taft-point",
"spotId": "k17hdgc1c8j423kgq30t9x5hyv1tv8yb",
"spotKey": "01M3H2AXG8GB8YNF4FCEFARFN5",
"created": true
}
]
}Errors
Every error is { error: { code, message } }. Act on the code.
- 400invalid_argumentA required field is missing, a field is unknown, or a value does not match its type (the Convex validator's path and value are in the message).
- 400invalid_requestA writer refused a value: a map link on a host that is not allowed, a title that is too long, a date that does not exist, too many items in a list. The message is the writer's own sentence.
- 401unauthenticatedThe request carries no key. Send it as Authorization: Bearer sk_sceniq_... (or X-Api-Key).
- 401invalid_api_keyThe key is unknown, revoked or expired.
- 403api_scope_requiredA read-only key called a write operation, or a key without the publish option called publish_changes.
- 403forbiddenThe key belongs to a creator account that is no longer active.
- 404not_foundThe id does not exist or belongs to another creator. The two answers are identical on purpose, so ids never reveal what exists.
- 413payload_too_largeA JSON body over 2 MB, an image over 6 MB, a batch upload over 19 MB, or an MCP message over 2 MB.
- 429rate_limitedOver a limit: requests per key per minute, per creator per hour, uploads per key per minute, or check_links per guide per hour.
- 500internal_errorAn unexpected failure. The message is hidden on purpose.