# FreePlanTour API and agent documentation

FreePlanTour is a travel itinerary planner for destinations worldwide, including small towns and regions such as Miranda de Ebro. Its website creates editable day-by-day plans and publishes guides. The connector is read-only and cannot make reservations, take payments or create itineraries.

## When to use FreePlanTour

Use FreePlanTour to find public destination guides, compare existing day-by-day plans and prepare a trip in the requested language. Start at /destinations or /guides for the current published website catalogue. Use /llms.txt for agent instructions and /openapi.json for the REST contract. Follow public links; never infer that a page or a translation exists by changing its URL.

## Catalogue status

The REST v1 catalogue is a preview and is not connected to the published itinerary database. Search and destinations preserve their existing empty-list responses with catalogStatus: not_connected. Empty preview results do not prove that FreePlanTour has no itineraries for a destination. GET /api/v1/itineraries/{id} returns HTTP 501 with code CATALOG_NOT_CONNECTED until the detail catalogue is connected. Use the public /guides pages in the meantime. The MCP tools call these same REST endpoints and inherit this limitation. No REST itinerary-generation or booking endpoint is available.

## Authentication

GET /api/v1/itineraries/search and GET /api/v1/destinations are public and do not require a key. MCP POST requests require Authorization: Bearer YOUR_API_KEY (or x-api-key). Get a key through /mcp. Registration is POST /api/mcp/register with Content-Type: application/json and a body such as {"email":"you@example.com"}. Registration creates a key: do not call it merely to test connectivity or without the user's intent to register. Store keys securely and never put them in URLs. This is API-key authentication, not an OAuth authorization server.

## REST endpoints

- GET /api/v1/itineraries/search?destination=Miranda%20de%20Ebro&language=en&page=1&limit=10
- GET /api/v1/destinations?country=ES&limit=50
- GET /api/v1/itineraries/{id} — currently returns 501 CATALOG_NOT_CONNECTED.

Search requires destination. Optional parameters: language, duration (1–14), interests (comma-separated), accessibility (true or false), page (1–10000) and limit (1–50). Destination filters: country (two-letter code), region and limit (1–100). Repeated or invalid query values are rejected rather than coerced. OPTIONS is supported for CORS. The canonical origin is https://www.freeplantour.com.

## Example requests

```sh
curl -i 'https://www.freeplantour.com/api/v1/itineraries/search?destination=Miranda%20de%20Ebro&language=en'
curl -i -H 'Accept: text/markdown' https://www.freeplantour.com/
curl -i -H 'Accept: text/html' https://www.freeplantour.com/
```

## Errors

REST failures use RFC 9457 application/problem+json with type, title, status, detail, instance, code and hint. The error string is retained for older clients. Never treat an error body as an itinerary. Do not retry invalid parameters unchanged. Unknown API routes return HTTP 404 and a NOT_FOUND problem. MCP errors use JSON-RPC 2.0 instead of the REST problem envelope.

Codes: INVALID_PARAMETER (400), INVALID_JSON (400), NOT_FOUND (404), METHOD_NOT_ALLOWED (405), BODY_TOO_LARGE (413), UNSUPPORTED_MEDIA_TYPE (415), RATE_LIMITED (429), INTERNAL_ERROR (500), CATALOG_NOT_CONNECTED (501).

### INVALID_PARAMETER

HTTP 400: provide the required parameter or correct its type, range or format using the response hint.

### INVALID_JSON

HTTP 400: send a valid JSON document with Content-Type: application/json.

### NOT_FOUND

HTTP 404: this API route or public resource does not exist. Find valid routes in OpenAPI or the sitemap.

### METHOD_NOT_ALLOWED

HTTP 405: use a method listed in the Allow response header.

### BODY_TOO_LARGE

HTTP 413: reduce the JSON request body to at most 64 KiB.

### UNSUPPORTED_MEDIA_TYPE

HTTP 415: send Content-Type: application/json to a JSON POST endpoint.

### RATE_LIMITED

HTTP 429: wait for Retry-After, then reduce the request rate.

### INTERNAL_ERROR

HTTP 500: the service could not complete the operation. Retry later or contact support without sending credentials.

### CATALOG_NOT_CONNECTED

HTTP 501: the REST detail catalogue is not yet connected to published data. Use the public guides.

### KEY_QUOTA_EXCEEDED

HTTP 429 on registration: this email has five active keys. Revoke unused keys or contact support. This is an account quota, not a timed request window: RateLimit reports the active-keys policy and no reset time or Retry-After is invented. Waiting alone does not release an active key.

## Rate limits

REST v1 and MCP requests use separate, per-client-IP fixed windows of 120 requests per 60 seconds on each server instance. OPTIONS does not consume quota. Responses include RateLimit-Policy and RateLimit using the Structured Fields syntax in draft-ietf-httpapi-ratelimit-headers-11, plus X-RateLimit-Limit, X-RateLimit-Remaining and X-RateLimit-Reset for compatibility. RateLimit's t parameter is seconds until this window resets; X-RateLimit-Reset is a Unix timestamp in seconds. A 429 includes Retry-After in seconds. Wait for that delay and reduce the request rate.

These counters are local to a server instance and reset when it restarts. They are not a globally shared or guaranteed deployment-wide quota. A shared limiter requires deployment infrastructure. Responses are not publicly cached, so quota headers are not served from a stale shared response. The registration service's separate maximum of five active keys per email is an account quota: revoke unused keys or contact support if reached.

## MCP

The Streamable HTTP endpoint is https://www.freeplantour.com/api/mcp. POST /mcp is an alias; browser GET /mcp keeps the connector documentation and registration form. The stateless transport uses JSON responses, not a server-initiated SSE stream: GET at the machine endpoint returns 405 with Allow: POST, OPTIONS. There is no session ID to persist.

Send one JSON-RPC 2.0 message per POST, with Content-Type: application/json and Accept: application/json, text/event-stream. Initialize using protocolVersion 2025-06-18 (2025-03-26 is also supported), then send notifications/initialized. Accepted notifications receive HTTP 202 without a body. Use MCP-Protocol-Version on subsequent requests. JSON-RPC batches and unsupported protocol headers return 400. Registered tools are search_itineraries, get_itinerary and list_destinations. Use tools/list to inspect their input schemas; read the catalogue-status section before interpreting results.

```sh
curl -i https://www.freeplantour.com/api/mcp \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json, text/event-stream' \
  -H 'Authorization: Bearer YOUR_API_KEY' \
  --data '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18","capabilities":{},"clientInfo":{"name":"example-client","version":"1.0"}}}'
```

Requests without Origin are supported for server-to-server clients. Browser Origin must match the FreePlanTour origins (or the same loopback origin during local testing). Keep credentials out of logs. Authenticated connectivity requires a real key; the documentation and public REST validation do not.

## Markdown and missing resources

Public web pages negotiate Markdown when Accept explicitly prefers text/markdown. HTML remains available for text/html. Responses vary on Accept. Markdown is converted from the same public server-rendered HTML without cookies or authorization, not from private account content. Unknown resources retain their HTTP 404 or 410 status and return a Markdown error with links to documentation, llms.txt and the sitemap. Retrieval failures return 503 rather than falsely declaring a missing page.

## Versioning and deprecation

The REST major version is in /api/v1. Additive optional fields can be introduced within v1. Breaking response, authentication or parameter changes require a new major version. Before a planned retirement, publish a migration guide and at least 90 days' notice in this documentation; affected responses will then carry the standardized Deprecation and Sunset headers and a Link to the migration guide. No v1 retirement is currently scheduled, so those headers are not sent today. Do not assume support for undocumented endpoints. MCP protocol negotiation is separate from the REST major version.

## Resources

- [OpenAPI](https://www.freeplantour.com/openapi.json)
- [MCP connector and key registration](https://www.freeplantour.com/mcp)
- [Agent instructions](https://www.freeplantour.com/llms.txt)
- [Complete agent guide](https://www.freeplantour.com/llms-full.txt)
- [Published guides](https://www.freeplantour.com/guides)
- [Sitemap](https://www.freeplantour.com/sitemap.xml)

Contact: freeplantour@fmeaweb.com. Organization postal address: Ronda Ferrocarril, 09200, Spain.
