Developer documentation

Integrate with Tankyu Distillery

This page documents the machine-readable surface of tankyudistillery.jp for AI agents, coding assistants, and partners building directories or commerce integrations. Everything here is read-only and requires no authentication.

Quickstart

Prefer JSON endpoints over HTML scraping. The four most useful discovery entry points:

curl https://tankyudistillery.jp/api/facts.json
curl https://tankyudistillery.jp/api/products.json
curl https://tankyudistillery.jp/api/tour.json
curl -H "Accept: text/markdown" https://tankyudistillery.jp/

All JSON endpoints are CORS-enabled (Access-Control-Allow-Origin: *) and cached for 24 hours at the edge.

Authentication

None. All public content and static JSON feeds are unauthenticated. The /.well-known/oauth-* and /.well-known/openid-configuration documents exist only for RFC 8414 / RFC 9728 compliance so agent-readiness probes can verify our access model. They declare empty response_types_supported and should not be treated as live OAuth endpoints.

POST form endpoints (/api/forms/*) are protected by server-side IP rate limiting (5 requests per 60 seconds). Agents must obtain explicit user consent before submitting these endpoints — each submission creates a real record with distillery staff.

Endpoints

Full OpenAPI 3.1 spec: /api/openapi.json.

MethodPathDescription
GET/api/facts.jsonCore distillery facts — location, water source, production capacity.
GET/api/products.jsonGin, whisky, and liqueur catalog as schema.org Product/Offer graph.
GET/api/tour.jsonTour price, duration, languages, schedule, booking URLs.
GET/api/pricing.jsonMachine-readable pricing table for tour, gin SKUs, private casks.
GET/api/press.jsonPress kit index — logos, boilerplate, founder bios.
GET/api/openapi.jsonOpenAPI 3.1 spec for form submission endpoints.
POST/api/forms/contactGeneral contact inquiry (rate-limited, user consent required).
POST/api/forms/tour-bookingDistillery tour booking (rate-limited, user consent required).
POST/api/forms/cask-inquiryPrivate cask consultation request (rate-limited, user consent required).
POST/api/forms/newsletterNewsletter subscription (rate-limited).
POST/api/forms/product-notifyProduct notification signup (rate-limited).

Markdown content negotiation

Every page on tankyudistillery.jp honours Accept: text/markdown via Netlify Edge middleware. The response body is our consolidated /llms-full.txt (~11 KB, comprehensive reference) with Content-Type: text/markdown; charset=utf-8 and Content-Signal: ai-train=yes, search=yes, ai-input=yes.

curl -sH "Accept: text/markdown" https://tankyudistillery.jp/ | head -40

Agent discovery surfaces

Content signals & crawl policy

Every response sets Content-Signal: ai-train=yes, search=yes, ai-input=yes. Per-bot overrides live in /robots.txt — for example, ChatGPT-User and PerplexityBot are allowed for search and input but excluded from training corpora, while Google Extended and Claude are allowed for training with our permission.

Code examples

bash

# Get the product catalogue
curl -s https://tankyudistillery.jp/api/products.json | jq '.["@graph"][].name'

# Submit a contact form (requires explicit user consent)
curl -X POST https://tankyudistillery.jp/api/forms/contact \
  -H "Content-Type: application/json" \
  -d '{"name":"Jane","email":"jane@example.com","subject":"Hello","message":"Hi","locale":"en"}'

TypeScript (fetch)

type TourInfo = {
  price: number
  currency: string
  duration: string
  languages: string[]
  bookingUrl: string
}

const res = await fetch('https://tankyudistillery.jp/api/tour.json', {
  headers: { Accept: 'application/json' },
})
if (!res.ok) throw new Error(`Tankyu API error: ${res.status}`)
const tour: TourInfo = await res.json()
console.log(tour.price, tour.bookingUrl)

Python

import requests

resp = requests.get(
    "https://tankyudistillery.jp/api/facts.json",
    headers={"Accept": "application/json"},
    timeout=10,
)
resp.raise_for_status()
facts = resp.json()
print(facts["@graph"][0]["name"])

Rate limits

Read-only JSON endpoints are CDN-cached for 24 hours and have no user-visible rate limit. Form POST endpoints are rate-limited to 5 requests per 60 seconds per IP. Exceeded limits return HTTP 429 with a JSON body:

{
  "error": {
    "code": "rate_limited",
    "message": "Too many requests. Please retry after the Retry-After window.",
    "documentation_url": "https://tankyudistillery.jp/developers#rate-limits"
  }
}

Error responses

/api/* endpoints (both static JSON and form POSTs) return structured JSON on error, never HTML. Shape:

{
  "error": {
    "code": "validation_failed" | "not_found" | "rate_limited" | "internal_error",
    "message": "human readable description",
    "documentation_url": "https://tankyudistillery.jp/developers#errors",
    "details": { /* optional per-field info */ }
  }
}