A ready trip.
One link to make it yours.
Create an itinerary from our public destination catalogs, then send a link the traveller can open, edit and save. No account or booking is needed to make a plan.
Planning with an AI assistant? Start with the copyable trip brief. For the planner controls, see saving and sharing a trip. This page documents the planning checklist and technical link format.
From a request to an editable trip
- Understand the trip. Use the traveller’s destination, dates, adults, rooms and interests. Ask for essential missing details; label any assumptions. One link holds one destination. Supported destinations are Dubai, Cancún, Miami Beach, Phuket, Koh Samui & Koh Phangan, Ibiza, Mykonos.
- Read its current catalog. Choose an exact stay ID and exact stop IDs from the data below. Match budget, access rules and preferences using the available evidence. A catalog is a dated research snapshot; it is not live inventory.
- Make a proposed itinerary. Use local calendar dates and local times. Keep scheduled stops between check-in, inclusive, and checkout, exclusive; leave
day: nullfor ideas to decide later. Set every stop’sconfirmedandgeneratedtofalse. - Encode and return the complete link. Follow the exact packet and UTF-8 encoding below. Present it as “Open your suggested trip” with a short explanation of dates, stay and stops. Preserve the entire
#trip=…fragment; no account, API key or POST request is needed. - The traveller previews it. The destination page opens a trip preview. They choose Open my own copy to add a new trip on their device. Existing trips remain, and the traveller can change dates, replace stops and follow booking links.
A planned trip is not a reservation. Do not describe a stay, table, ticket or event as booked. The traveller verifies availability, prices, admission and any booking terms with the provider. Booking confirmations do not transfer through trip links.
Make a useful plan before encoding it
- Get the constraints that change the answer. Ask for destination, local check-in/checkout dates, arrival/departure windows, adults, rooms, private room or dorm, pace, nightlife interests, noise tolerance and transport or mobility needs. Clarify budget currency and whether accommodation spend is per room per night or for the whole stay; separate food, tickets and transport. Label assumptions and keep private identity/payment/booking information out.
- Explain the stay choice. Compare two suitable options and one tradeoff for each using the destination guide, access notes and original sources. Distinguish a hotel party from an external night out and a room benefit from a separate ticket. A score is not a substitute for the traveler's preferences, and the catalog does not contain live room prices or availability.
- Make the days feasible. Keep arrival light, allow rest after late nights, group stops using real routes and allow transfer buffers. A straight-line distance is not a walking route or journey time. Check the return journey as well as the outbound trip; if transport or timing is unknown, say so rather than assigning invented clock times.
- Handle midnight and checkout explicitly. Read the operator's date/time convention before interpreting an after-midnight listing. Use the actual local calendar date and time when established; do not silently move an event to the preceding evening. Scheduled item dates run from check-in inclusive to checkout exclusive. Put checkout travel or an out-of-range late-night note in the summary instead of creating an invalid stop.
- Keep evidence and booking status separate. Inspect source dates, cancellation and seasonal limits. Never move a one-off event onto a requested night or extrapolate a future season. Explain which details are source-verified and which need checking, while keeping every suggested stop
confirmed: falseandgenerated: false. Offer a suitable alternative or free time if a night is unavailable or unverified. - Show the limits of coverage and cost. The catalogs are a curated stay and nightlife sample, not complete city guides. Dining coverage varies by destination; some restaurants appear only in the venue catalog. There is no live price feed. Dining, daytime and transport gaps require fresh primary-source research or free-time placeholders. Separate accommodation, meals, tickets, transport and extras; distinguish dated provider quotes from estimates and unknown costs.
Read the full place record. Combine experiences[] and venues.venues[] by exact ID, merging shared IDs while retaining places found only in one array. Important hours, entryNote, age or transport details can be present only in the venue record; experience admission uses inclusions.Entry. Check both and their sources. A generic label must not override a specific eligibility rule. Cancún’s venue catalog includes dining places such as mextreme-cancun that have no matching experience record; those venue IDs are valid planner references too.
Do not turn a snapshot into a promise. A verified_open status does not establish future opening. Expired validUntil or requested dates outside verified coverage require a fresh operator check or clearly tentative/unscheduled alternatives. Not every stay has a verified map pin: confirm the exact address and route instead of inferring travel time from its area. Check boat transfers, seasonal boarding points and return services where applicable.
Keep the real group intact. The link format supports 1–8 adults and 1–4 rooms, no more rooms than adults, and no children field. Do not encode children as adults, clamp a larger group or omit travelers. Explain unsupported occupancy and return a plain itinerary with provider checks when the group cannot be represented.
Use exact catalog IDs for catalog places. For an independently researched outside-catalog idea, use refId: null, an honest customName, and a concise source/caveat note; keep fuller evidence in the accompanying response. For unscheduled ideas use day: null. Do not invent an ID or imply the site researched that venue.
Return the complete link alongside a short stay recommendation, daily outline, sources/check dates, cost uncertainties and the practical checks still needed. If current data cannot be fetched or a valid link cannot be encoded, provide a plain suggested itinerary and explain the limitation.
Destinations & public data
Fetch the selected destination’s JSON when preparing the link. These are the same catalogs used by the website. Read destination.id and destination.timezone to confirm the destination.
| Destination | Catalog | ID / local timezone |
|---|---|---|
| Dubai | dubai-data.json | dubaiAsia/Dubai |
| Cancún | data.json | cancunAmerica/Cancun |
| Miami Beach | miami-data.json | miamiAmerica/New_York |
| Phuket | phuket-data.json | phuketAsia/Bangkok |
| Koh Samui & Koh Phangan | samui-phangan-data.json | samui-phanganAsia/Bangkok |
| Ibiza | ibiza-data.json | ibizaEurope/Madrid |
| Mykonos | mykonos-data.json | mykonosEurope/Athens |
stays[] contains hotels and hostels. experiences[] contains places and activities. events.events[] contains dated events, and venues.venues[] holds additional venue detail. Use an entry’s id, not its display name or URL, in the trip. A place can appear in both experiences and venues; deduplicate by ID and read the venue detail too.
events.recurringPrograms[] contains published weekly programs. Read daysOfWeek as local weekdays: numbers 1–7 mean Monday–Sunday; records may instead use English weekday names or abbreviations. Match the trip dates against the weekdays and any seasonStart, seasonEnd and validUntil limits, then verify the actual date with the operator. A weekly pattern is not a confirmed dated event.
A recurring program’s id is not a planner stop ID. Use its venueId as refId only if that ID exists in the destination’s stays, experiences or venues; otherwise use refId: null with an honest customName. Read the name from title or name, and the explanation/caveat from summary or confirmationNote. Read time, then publishedTime, then startTime/endTime as available; retain uncertainty in the published wording. Follow official or sources[].url for the recorded operator evidence. Name the program and source caveat in the stop note, and keep confirmed: false. For an overnight program, distinguish the starting weekday from its after-midnight end and check the operator’s local-date convention.
For evidence, inspect checked, validUntil, seasonStart, seasonEnd, verifiedForDatesThrough, status, caveat, entryNote, agePolicy and inclusions where available. Follow official, source and sources[].url to verify uncertain or dated details. Missing fields are unknown. A freshness date alone does not establish opening or availability for a future visit.
Place a dated event only between its startDate and endDate, using startTime when documented. Never repeat a one-off event on another date or infer next season’s programme. Observe cancellation, seasonal, guest-only and age restrictions. If evidence does not cover the requested dates, choose another stop or clearly label it as a tentative idea with details to verify.
Exact link format · version 1
https://goaftercheckin.com/{destinationId}#trip={base64url}
base64url is UTF-8 JSON encoded as URL-safe base64 without = padding. Replace + with - and / with _. Do not call btoa() directly on Unicode JSON, percent-encode the payload, add query parameters, or append another fragment. The hosted site redirects .html routes to their clean URL; the browser retains the trip fragment.
| Field | Value |
|---|---|
format / version | Exactly "after-check-in-trip" and number 1. |
destinationId | "dubai", "cancun", "miami", "phuket", "samui-phangan", "ibiza", "mykonos"; must match the destination page and catalog. |
name | A short, non-sensitive trip title; maximum 60 text units. |
plan.version | Number 1. |
plan.trip | {checkin, checkout, nights, adults, rooms}. Real YYYY-MM-DD dates; 1–90 nights; integer adults 1–8; integer rooms 1–4 and no more than adults. The reader recalculates nights. Use null only when dates are undecided. |
plan.hotelId | An exact stays[].id from this destination, or null for no selected stay. Maximum ID length 100. |
plan.alternates | Array of up to 12 distinct stay IDs, or []. |
plan.pace | "easy", "balanced" or "full". |
plan.note | Optional planning text, maximum 1,500 text units; use "" for none. |
plan.items | Array of up to 200 stops. Each uses the item fields below. The byte limit usually requires a much smaller plan. |
Each stop in plan.items
Set refId to an exact catalog ID and customName to "". For a personal activity such as “Free afternoon”, use refId: null and a customName of up to 100 text units. Do not use a custom name to imply that an unverified venue is in the catalog.
Include day (YYYY-MM-DD or null), time (local 24-hour HH:mm or ""), note (up to 500 text units), confirmed: false and generated: false. generated is reserved for the site’s own suggestion lifecycle. Item uid values are unnecessary; the reader creates new ones.
Text limits use JavaScript UTF-16 string length; some emoji use more than one text unit. The decoded JSON must be at most 12,000 UTF-8 bytes and the full URL at most 16,000 characters. Use short notes and fewer stops to stay below both limits. Invalid stay IDs are cleared and unknown stops without a custom name are dropped; verify every ID before returning the link. The decoder checks the format, but does not verify bookings, opening hours or itinerary feasibility.
A complete working example
Two adults, one room, 5–8 March 2027, with Riu Caribe as a suggested stay, a beach idea at Playa Delfines and a tentative Coco Bongo night. These are real catalog IDs and illustrative dates. No future opening, event programme, price or availability is claimed.
Open the example tripDownload the complete JSON packet and standalone JavaScript encoder. Update the example’s dates and selections for the traveller; do not reuse its dates as a default. The packet is for a link, not the planner’s Load file control.
View the complete example packet
{
"format": "after-check-in-trip",
"version": 1,
"destinationId": "cancun",
"name": "Cancún · beach + nights",
"plan": {
"version": 1,
"trip": {
"checkin": "2027-03-05",
"checkout": "2027-03-08",
"nights": 3,
"adults": 2,
"rooms": 1
},
"hotelId": "riu-caribe",
"alternates": [],
"pace": "balanced",
"note": "Example itinerary only. Check opening dates, admission and availability before booking.",
"items": [
{
"refId": "playa-delfines",
"customName": "",
"day": "2027-03-06",
"time": "",
"note": "A beach idea; check local conditions.",
"confirmed": false,
"generated": false
},
{
"refId": "coco-bongo-cancun",
"customName": "",
"day": "2027-03-07",
"time": "",
"note": "Tentative night out; verify the programme and tickets for this date.",
"confirmed": false,
"generated": false
}
]
}
}Executable JavaScript encoder
This function works in modern browsers and Node.js 18+. Pass the packet above to encodeTripLink(packet). It encodes the supplied packet and checks the byte limit; choose and validate dates and catalog IDs before calling it.
// Standalone encoder for the documented v1 trip-link packet.
// Fetch /trip-link-example.json for a complete example; replace its dates and
// selections using the user's request and the destination's current catalog.
// This encodes a packet; it does not verify bookings, dates or catalog IDs.
export function encodeTripLink(packet) {
if (packet?.format !== 'after-check-in-trip' || packet.version !== 1 || packet.plan?.version !== 1) {
throw new Error('Use the documented version 1 trip packet.');
}
if (!["dubai","cancun","miami","phuket","samui-phangan","ibiza","mykonos"].includes(packet.destinationId)) {
throw new Error('Choose a supported destination.');
}
const bytes = new TextEncoder().encode(JSON.stringify(packet));
if (bytes.length > 12000) throw new Error('Trip packet exceeds 12,000 UTF-8 bytes.');
let binary = '';
for (const byte of bytes) binary += String.fromCharCode(byte);
const encoded = btoa(binary).replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '');
const link = `https://goaftercheckin.com/${packet.destinationId}#trip=${encoded}`;
if (link.length > 16000) throw new Error('Trip link exceeds 16,000 characters.');
return link;
}
Browser example, run from an After Check-in page:
const { encodeTripLink } = await import('/trip-link-example.js');
const packet = await (await fetch('/trip-link-example.json')).json();
const link = encodeTripLink(packet);
console.log(link); // Return this complete URL to the traveller.
Verify with the website’s own decoder
The public trip-sharing.js module exports createTripShareUrl and readSharedTrip; it imports trip-store.js. In a browser on this site, or after downloading both modules together for local use, validate the link against the selected catalog:
const { readSharedTrip } = await import('/trip-sharing.js');
const catalog = await (await fetch('/data.json')).json(); // Cancún
const decoded = readSharedTrip(link, packet.destinationId, catalog);
if (!decoded || decoded.droppedItemCount ||
decoded.plan.hotelId !== packet.plan.hotelId ||
decoded.plan.items.length !== packet.plan.items.length ||
!['checkin', 'checkout', 'nights', 'adults', 'rooms'].every(
key => decoded.plan.trip?.[key] === packet.plan.trip?.[key])) {
throw new Error('Review the dates and catalog IDs before sharing.');
}
For another destination, change the catalog path as listed above. Also compare the decoded stops’ dates, times and IDs with what you intended. A successful decode means the link can be read; it does not establish that the proposed trip can be booked.
For search and agent discovery
Start at llms.txt for a compact index of this guide and the catalogs. The robots policy describes crawling permissions, and the sitemap lists public pages. Trip creation instructions live here so they can be read independently of crawler rules. Publishing these resources makes the workflow discoverable; each search engine and assistant decides whether to index or use them.
Questions or a broken link? Contact After Check-in.