# FORKPIN Gateway

We provide restaurant identity, platform membership, observed facts and evidenced handoff URLs. We do not execute reservations or orders, determine seats or queue capacity, or guarantee live opening hours.

Send the restaurant name in Hangul when you have it; English or romanized names also work. Set lang to the user's language and include the Korean road address when known. Send the user's language as lang (for example en).

Human homepage: https://www.forkpin.kr/. Agent page: https://www.forkpin.kr/agent. Agent directory: https://www.forkpin.kr/agent/directory.

## Connect an agent instance
Public reads need no key or login. MCP register creates a scoped unverified instance without prior authentication; retain Mcp-Session-Id for subsequent calls, or use the returned API key in X-Agent-Key when a client does not keep sessions. Sessions expire after 15 minutes. Certification remains a separate operator decision.
에이전트는 자동 등록 후 즉시 미인증 키를 받습니다. 만료 7일 전부터 기존 키로 병행 갱신할 수 있고, 유출 시 즉시 폐기 재발급합니다. 키를 분실하면 지원 창구에 관리자 재발급을 요청합니다.
POST https://www.forkpin.kr/v1/agents/register with product, label and intended_use. Save the returned api_key once, then send X-Agent-Key: api_key on authenticated calls. From 7 days before expiry, POST /v1/agents/key/renew with the current X-Agent-Key to receive a new key; the old key works until its original expiry. For a compromised key, POST /v1/agents/key/rotate revokes all old credentials immediately. Without the old key, request owner-admin reissue through https://www.forkpin.kr/support. No approval or polling is required for self-registration; this is not MCP OAuth discovery.

## One-time agent consent
Agents are free. Read GET /v1/agents/consent. Accept all three terms once per instance: routing handoffs through FORKPIN, signed handoff tokens without customer identity, and structured outcome telemetry without customer identity. Include consent in registration or POST /v1/agents/consent with version=agent-consent-v1 and routed_via_cooksup, signed_handoff, outcome_telemetry all true using the instance credential. Certification alone does not imply consent. Without consent, reads and evidenced route URLs remain available, but no signed token is issued. Acceptance is recorded with version, instance id and time; repeated acceptance preserves the time. Existing unsigned intents stay unsigned.

## Your identity and credit ledger
After registration, authenticate and call get_agent (GET /v1/agents/me) to confirm the stable instance id, owner-link status, scopes and consent state. After explicit consent, call get_credits (GET /v1/agents/credits) for balance, next expiry and the latest 100 entries. Keep access, refresh and API keys in your vault. Owner-admin reissue is available through support if the key is lost; expiration renewal and emergency rotation both require the current key.

## Catalog pages
Call catalog or GET /catalog.json without filters for page one. When has_more is true, pass next_page.after and next_page.part as after and part; preserve name and area filters. Do not pass the response keys next_after or next_part as query names.

## Registered areas and coverage
Call list_areas (MCP first or full) or GET /v1/public/areas (REST) to see the registered area names and collection progress. Each area count and the overall coverage come from the same gatewayCounts snapshot as /agent.json, with as_of. Coverage is not a verified restaurant or available route.

## Narrow known options and weekly hours
Use search_places (MCP) or POST /v1/search_places (REST) with required_options such as ["parking","kids_allowed"] and open_on such as {"day":"sat","time":"18:00"}. Only projected true options and matching weekly hours enter places. Condition-only results use neutral address order and return result_count, returned_count and next_cursor for further pages. Missing, null, or unknown facts appear separately in unknown_places; known false or closed hours appear in excluded. Each matched condition reports verification_status; displayed means the platform showed it, not that the venue or live opening was confirmed. Time is local within the named service day. This changes no route order, score or reservation availability. Reread get_place before handoff.

## Empty fact fields
Read unknown_fields for each absent fact: not_shown means an explicit unknown FieldObservation was projected, with observed_at and source_url; not_observed means no eligible field observation exists. collection_attempted_at only proves a place collection attempt, not a check of that fact. Neither state means false, closed or unavailable. The legacy unknown list remains for compatibility.

## Read, hand off, report
Send purpose=visit, reserve or delivery to resolve, get_place or search_places for one route_for_purpose with steps, evidence and confirmation time; none means no verified path for that purpose. Call resolve once with name and address (or a query containing both, or a deterministic id), action, context and intent_key: a matched response includes place, policy, preflight and a handoff. A name without an address or supplied area never confirms: it returns address-labeled candidates in pages of 20. One exact name unique in a supplied area may identify the place for a read-only answer; it never issues a booking handoff without the road address. Read next_action: answer means an identified fact, ask_user means list branch candidates and ask for the address, and hand_off means the requested evidenced link is present. Supply action or purpose explicitly. If omitted from a free-text resolve or search query, a bounded OpenAI check may select a link action marked derived; it never changes restaurant order or score, and timeout, error or budget exhaustion uses the static link behavior. Separate get_place/get_routes reuse the same intent and token. Then open an evidenced URL, and report outcomes or observations with persistent request_id. Read /v1/reports/{report_id} for your private receipt. Only reviewed structured observations are reused. Unknown is not false. A copied snapshot must be reread before handoff. Collected Naver membership hands off to the observed Naver Place URL for info. A recorded reservation indicator may use that Place URL until an observed direct Naver booking URL is available; neither is a completed booking. Other platforms are membership facts with url null. Facts retain source_read_at and source_updated_at separately from confirmed_at and observed_at. Likes are aggregate metadata, not people or recommendations. Do not send customer identity or secrets.

## Free reads and trust credits
Agents pay no money. After registration and explicit consent, the first instance from a source receives five trust credits once per thirty-day window; later registrations from that source receive none. A new signed intent costs one; identical retries cost zero. Operationally verified contributions earn one, up to five per Seoul calendar day and one per place per day. Credits expire after thirty days. GET /v1/agents/credits reads the authenticated instance ledger. No consent or no credit leaves evidenced URLs and unsigned handoffs available in the same order. Prior unsigned intents are never upgraded by a retry.

## One intent, one attempt
Supply intent_key (8-100 ASCII characters) on get_place, resolve or get_routes. Retry with the same key and token; never poll availability. Only one handoff is issued for the selected route. Automatically registered instances remain unverified; certified authenticated instances that accepted agent-consent-v1 and have trust credit receive an Ed25519 signed token. A clearly marked demo merchant may sign for an unverified consenting instance with trust credit; real merchants cannot use this exception. The token is valid for ten minutes with iss=FORKPIN (legacy COOKSUP tokens remain verifiable). Token delivery is optional in phase 1; keep the certified-instance flow. Forward the token in the COOKSUP-Handoff header. Only when headers are unavailable, use cooksup_handoff as a URL query parameter; URLs may leak into logs and referrers. Verify it with /.well-known/handoff-jwks.json and deduplicate its jti atomically at the platform. A signature is not replay prevention or a reservation. Changed intent or destination is 409; an expired token is not renewed by retry. Preflight checks party size and supported booking rules, keeps availability unknown, and does not store customer or raw booking intent.

## Restaurant agent policy
Read the FORKPIN normalized agent_policy before any automated attempt. Policies are processed and supplied through FORKPIN API/MCP, not a public self-publishing standard. Reread /v1/restaurants/{place_id}/agent-policy using ETag and If-None-Match; a 304 means unchanged. Honor refresh_after_hours (default 24). It is null when unknown. Fresh allowed or conditional declarations select official channels in their declared order; obey booking_rules, notes and etiquette. Check direct_booking, requires_login and account; reservation, modify and cancel can use different channels. Ask for explicit user approval when requires_human_approval is true. Channel operators govern their own channel; conflicts are disclosed in conflicts[]. Disputed channels are held until operational review. Minute/hour limits are per authenticated instance and channel. User choices cannot override shared-resource etiquette. Disallowed prohibits automatic attempts while identity and facts remain readable. Expired policies carry policy_stale and caution; use existing evidenced routes instead. Route order has no commercial or fixed platform preference. Report policy_channel_attempted (boolean) and policy_result (success, blocked, info_mismatch) together in report_outcome. Reports enter review, never change policy automatically.

Legal review pending. This policy is advisory information declared by a restaurant or platform, or checked by FORKPIN. Final authority rests with the restaurant or platform. FORKPIN does not execute reservations.

## Failure and limits
401 agent_auth_required/invalid_agent_key/token_expired: register or reconnect. 403 scope_required: ask the owner for permission. 429 rate_limited: honor Retry-After. A timeout or judgment failure returns static basis and degraded true. 503 service_unavailable: use existing search. Unmatched identity asks for clarification; unknown_place is 404. Anonymous reads can use JEV: up to 100 evaluations per IP per Seoul calendar day, within 50% of the shared $1 daily input-token budget. The remaining budget is protected for registered agents and operations. Quota, budget exhaustion, timeout or failure returns static basis and degraded true. Deterministic license/place ids or one exact normalized license name and road key can still identify a restaurant; On degraded JEV, one exact customer-facing name at the supplied road address can also identify a restaurant when company/hotel prefix evidence and all building names establish uniqueness; identity_evidence records this proof. Partial names, ambiguous branches or duplicate names require clarification. Regional candidates can still be returned with conditions_verified=false, unknown conditions and clarification; they do not satisfy unverified requirements. See /agent.json for configured limits.

Contract 2026-09-29.23; /agent-changelog.json records changes. Connect https://www.forkpin.kr/mcp. 

## For English-speaking travelers
Use lang=en on resolve, search_places, catalog, get_place or read_restaurant. Send the user's language as lang (for example en). Missing lang with a Latin-only name or query is an English-speaking user and sets lang_inferred. Hangul text, or no Latin text, stays Korean. Explicit lang wins. The display block retains the original Korean name and address. Observed English names and aliases retain their source. Romanization and rule-based English road addresses are derived, never verified or official names. No name translation creates a new restaurant. For identity queries, exact self-names precede observed aliases and derived romanization; aliases and romanization alone never confirm a place. Condition searches return paged regional candidates, ordered by supplied WGS84 distance or a daily rotation of query and license id, never popularity, payment or merchant registration. Route order remains unchanged.

Error mapping: AMBIGUOUS → branch_conflict or weak_address; NOT_FOUND → unknown_place; CHANNEL_UNVERIFIED → candidates with url null; RATE_LIMITED → HTTP 429 and Retry-After; FORBIDDEN → HTTP 403; PARTIAL_SUCCESS → get_place places plus errors. Report four observed axes separately: identity (correct_place/wrong_shop), link (route_reachability/wrong_link), execution (execution.confirmed/completed or opened_not_completed), and data problems (field_errors/info_wrong).

Connector description: Exact Seoul restaurant branch from name and address, plus sourced hours, menu and booking-page links where observed. Never books, pays or checks live seats.

Start with a recorded Myeongdong example: GET https://www.forkpin.kr/v1/restaurants/3010000-101-1971-06619 for Grand Kitchen at 61 Myeongdong-gil (Myeongdong 1-ga). Read the returned direct reservation handoff, menu, observed hours, options and amenities with each verification_status. The hours text is an observation, not today's schedule or live availability; use unknown_fields for absent weekly hours. Then resolve the same name and road address before opening the returned provider URL.

Example questions (answers depend on recorded evidence):
1. Is there an online booking page for Aria (아리아) at 서울특별시 중구 소공로 106, and what are its Saturday opening hours?
2. Is there an online booking page for Grand Kitchen (그랜드 키친) at 서울특별시 중구 명동길 61, and what does its menu list?
3. Which restaurant is 명동교자 (Myeongdong Kyoja) at 서울특별시 중구 명동10길 10, and what hours does it show?
4. Which restaurants near Myeongdong have an online booking page I can open?
5. Which Myeongdong restaurants show parking?
6. Which Myeongdong restaurants show Saturday opening hours that cover 6 p.m.?

Service information: https://www.forkpin.kr/privacy, https://www.forkpin.kr/terms, https://www.forkpin.kr/support. Legal review is pending.

Phone handoff policy: disclose AI identity when a call starts, or disclose that a person is calling on the agent’s behalf. Get consent before recording or transcribing. Share only booking-necessary details with the provider. FORKPIN does not place calls or store guest personal data.
