{"openapi":"3.1.0","info":{"title":"hanko.works public API","version":"1.0.0","summary":"Read-only access to what hanko.works sells and to the seal designs a name gets.","description":"hanko.works composes a custom Japanese seal (hanko, 印鑑) for one name and machines it in aluminium or titanium in Japan; nothing is carved until the customer approves the exact face. Ships within Japan only.\n\nThis API is for programs and AI agents helping a person choose a seal. It reads: the catalogue, the eight designs for a name with their eligibility for each use, and rendered impressions. It never writes — ordering happens in the browser at the `orderUrl` each design carries.\n\nNo authentication, no key, CORS open. Prices are in Japanese yen, tax included. Every error is JSON in the `ApiError` shape with a stable `code`, a `message`, a `hint` and, when there is one, the `param` at fault; unknown `/api/*` paths answer 404 in the same shape.","termsOfService":"https://hanko.works/en/developers","contact":{"name":"hanko.works","email":"hello@hanko.works","url":"https://hanko.works/en/contact"}},"servers":[{"url":"https://hanko.works","description":"Production"}],"externalDocs":{"description":"For developers and agents","url":"https://hanko.works/en/developers"},"tags":[{"name":"catalog","description":"What is on offer."},{"name":"designs","description":"The designs a name gets."},{"name":"seal","description":"One rendered impression."}],"paths":{"/api/v1/catalog":{"get":{"operationId":"getCatalog","tags":["catalog"],"summary":"The catalogue","description":"Sizes, the four uses with their recommended size bands and recommended design family, the two metals with prices, lead times and colours, the two shapes, the eight design families and which uses each is sold for, add-ons, the corporate set, gift tiers, shipping, cancellation and guarantee terms. Call it once and cache it; it changes only when the catalogue does.","responses":{"200":{"description":"The catalogue.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Catalog"}}}}}}},"/api/v1/designs":{"get":{"operationId":"listDesigns","tags":["designs"],"summary":"The eight designs for a name","description":"One design per family (the same sheet the customize page shows), each with the geometry's eligibility report at the requested size, whether it is sold for and passes the requested use, a preview URL (an SVG impression) and the URL where a person orders exactly this configuration. `index` selects another sheet of eight for the same name. Deterministic: the same parameters always return the same designs.","parameters":[{"name":"name","in":"query","required":true,"description":"The name to compose: kanji, kana or Latin, up to 12 characters. Latin is carved as Latin; it is never transliterated.","schema":{"type":"string","minLength":1,"maxLength":24,"examples":["山田","Tanaka","田中花子"]}},{"name":"use","in":"query","description":"What the seal is for. Decides the recommended family and which designs count as eligible.","schema":{"type":"string","enum":["bank","registered","everyday","corporate"],"default":"registered"}},{"name":"size","in":"query","description":"Diameter (or side) of the impression in mm. Not every size exists in every shape — round is 12–18, a rounded square 15–24 (`sizesByShape` in the catalogue) — and a pair that does not exist is a 400. The catalogue also gives the band recommended for each use.","schema":{"type":"number","enum":[12,13.5,15,18,24],"default":15}},{"name":"material","in":"query","description":"The metal; decides the price and lead time.","schema":{"type":"string","enum":["aluminium","titanium"],"default":"titanium"}},{"name":"shape","in":"query","description":"Force every design into one silhouette. Omit it and each design keeps its family's own shape (`defaultShape` in the catalogue).","schema":{"type":"string","enum":["round","square"]}},{"name":"index","in":"query","description":"Which sheet of eight designs: 0 is the first, up to 39.","schema":{"type":"integer","minimum":0,"maximum":39,"default":0}},{"name":"locale","in":"query","description":"The language the `orderUrl` opens in.","schema":{"type":"string","enum":["en","ja"],"default":"en"}}],"responses":{"200":{"description":"The designs.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DesignSheet"}}}},"400":{"description":"A parameter is missing or invalid; `error.param` names it and `error.hint` says what is accepted.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"The engine could not compose the name.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/seal":{"get":{"operationId":"renderSeal","tags":["seal"],"summary":"One rendered impression","description":"The impression of one design as an SVG (`view=svg`, the default) or, with `view=json`, the face geometry for a 3D stage plus the eligibility report at `size`. A pure function of its parameters, so the answer is immutable and safe to cache forever; a strong ETag is returned and `If-None-Match` is honoured. Identify the design by `seed` (from `listDesigns`) or by `index` (the n-th design of the name in this family).","parameters":[{"name":"name","in":"query","required":true,"description":"The name to compose: kanji, kana or Latin, up to 12 characters. Latin is carved as Latin; it is never transliterated.","schema":{"type":"string","minLength":1,"maxLength":24,"examples":["山田","Tanaka","田中花子"]}},{"name":"family","in":"query","required":true,"description":"The design family (script).","schema":{"type":"string","enum":["insou","tensho","reisho","kaisho","koin","kaku","wave","vortex"]}},{"name":"seed","in":"query","description":"The design seed, as returned by `listDesigns`. Wins over `index` when both are given.","schema":{"type":"integer"}},{"name":"index","in":"query","description":"The n-th design of this name in this family (0 = the first), when no `seed` is given.","schema":{"type":"integer","minimum":0,"maximum":99}},{"name":"view","in":"query","description":"`svg` for the impression, `json` for geometry + eligibility.","schema":{"type":"string","enum":["svg","json"],"default":"svg"}},{"name":"size","in":"query","description":"Impression size in mm, used by `view=json` for the eligibility report and the geometry scale.","schema":{"type":"number","minimum":8,"maximum":30,"default":15}},{"name":"shape","in":"query","description":"Force the silhouette, in the store's vocabulary; omit for the family's own. `silhouette` wins when both are given.","schema":{"type":"string","enum":["round","square"]}},{"name":"mirror","in":"query","description":"`1` renders the carved face (mirrored) instead of the impression.","schema":{"type":"string","enum":["0","1"],"default":"0"}},{"name":"ink","in":"query","description":"Fill colour of the impression, `#RGB` or `#RRGGBB`. The colour, not the polarity — for that, see `mode`.","schema":{"type":"string","pattern":"^#(?:[0-9a-fA-F]{3}|[0-9a-fA-F]{6})$","default":"#D9381E"}},{"name":"mode","in":"query","description":"Ink polarity: `shubun` red characters on paper, `hakubun` paper characters on a solid red field, `split` one of each side of a dividing line (朱白相間). Omit for `shubun`.","schema":{"type":"string","enum":["shubun","split","hakubun"],"default":"shubun"}},{"name":"silhouette","in":"query","description":"Force the silhouette, in the engine's own vocabulary — `ellipse` included, which the store does not sell. Omit for the family's own.","schema":{"type":"string","enum":["circle","ellipse","square","roundedSquare"]}},{"name":"frame","in":"query","description":"Frame band width as a fraction of the seal's radius, 0.01 to 0.18, step 0.005. Omit for the family's own (they differ).","schema":{"type":"number","minimum":0.01,"maximum":0.18}},{"name":"deform","in":"query","description":"Map the whole face between disc and square: `elliptical` (round mapping) or `fgSquircle` (crisper corners), applied in full. Omit for `none`, which is how every design is composed.","schema":{"type":"string","enum":["none","elliptical","fgSquircle"],"default":"none"}},{"name":"weight","in":"query","description":"Style tweak — weight: -14 to 24, step 0.5. Omit for the seeded design.","schema":{"type":"number","minimum":-14,"maximum":24}},{"name":"reach","in":"query","description":"Style tweak — reach: 0 to 1, step 0.01. Omit for the seeded design.","schema":{"type":"number","minimum":0,"maximum":1}},{"name":"fan","in":"query","description":"Style tweak — fan: 0 to 1, step 0.01. Omit for the seeded design.","schema":{"type":"number","minimum":0,"maximum":1}},{"name":"scatter","in":"query","description":"Style tweak — scatter: 0 to 1, step 0.01. Omit for the seeded design.","schema":{"type":"number","minimum":0,"maximum":1}}],"responses":{"200":{"description":"The impression, or the geometry and eligibility.","headers":{"ETag":{"description":"Strong; the answer never changes for these parameters.","schema":{"type":"string"}},"Cache-Control":{"schema":{"type":"string","const":"public, max-age=31536000, immutable"}}},"content":{"image/svg+xml":{"schema":{"type":"string","description":"The impression as an SVG document."}},"application/json":{"schema":{"$ref":"#/components/schemas/SealJson"}}}},"304":{"description":"Not modified (`If-None-Match` matched)."},"400":{"description":"A parameter is missing or invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"The engine could not render the design.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}}},"components":{"schemas":{"ApiError":{"type":"object","description":"Every error the API returns, on every route.","required":["error"],"properties":{"error":{"type":"object","required":["code","message","docs"],"properties":{"code":{"type":"string","enum":["invalid_parameter","missing_parameter","not_found","method_not_allowed","render_failed"],"description":"Stable machine code."},"message":{"type":"string","description":"One sentence saying what is wrong."},"hint":{"type":"string","description":"What to change to succeed."},"param":{"type":"string","description":"The query parameter at fault, when there is one."},"docs":{"type":"string","format":"uri","description":"This document."}}}}},"Names":{"type":"object","description":"A label in both languages.","required":["en","ja"],"properties":{"en":{"type":"string"},"ja":{"type":"string"}}},"SizeBand":{"type":"object","required":["min","max"],"properties":{"min":{"type":"number","description":"mm"},"max":{"type":"number","description":"mm"}}},"Use":{"type":"object","required":["id","name","recommendedSizeMm","recommendedFamily"],"properties":{"id":{"type":"string","enum":["bank","registered","everyday","corporate"]},"name":{"$ref":"#/components/schemas/Names"},"recommendedSizeMm":{"$ref":"#/components/schemas/SizeBand"},"recommendedFamily":{"type":"string","enum":["insou","tensho","reisho","kaisho","koin","kaku","wave","vortex"]},"legalSizeMm":{"$ref":"#/components/schemas/SizeBand","description":"For the registered seal: the envelope ward offices accept by law (the band above is what we recommend)."}}},"Color":{"type":"object","required":["id","name","swatch"],"properties":{"id":{"type":"string"},"name":{"$ref":"#/components/schemas/Names"},"swatch":{"type":["string","null"],"description":"Hex; null for the bare metal."}}},"Material":{"type":"object","required":["id","name","priceJpy","corporatePriceJpy","leadDays","massG","colors"],"properties":{"id":{"type":"string","enum":["aluminium","titanium"]},"name":{"$ref":"#/components/schemas/Names"},"priceJpy":{"type":"integer","description":"One personal seal, any size or shape, tax included."},"corporatePriceJpy":{"type":"integer","description":"One company seal (use `corporate`), tax included."},"leadDays":{"type":"integer","description":"Calendar days from approval to dispatch."},"massG":{"type":"number","description":"Approximate mass of a 15 mm × 60 mm seal."},"colors":{"type":"array","items":{"$ref":"#/components/schemas/Color"}}}},"Family":{"type":"object","required":["id","name","defaultShape","uses"],"properties":{"id":{"type":"string","enum":["insou","tensho","reisho","kaisho","koin","kaku","wave","vortex"]},"name":{"$ref":"#/components/schemas/Names"},"defaultShape":{"type":"string","enum":["round","square"]},"uses":{"type":"array","items":{"type":"string","enum":["bank","registered","everyday","corporate"]},"description":"The uses this family is sold for."}}},"Catalog":{"type":"object","required":["currency","pricesIncludeTax","shipping","guarantee","seal","sizesMm","sizesByShape","uses","materials","shapes","families","addons","corporateSet","gifts","links"],"properties":{"currency":{"type":"string","const":"JPY"},"pricesIncludeTax":{"type":"boolean","const":true},"discounts":{"type":"boolean","const":false,"description":"Fixed prices; no sales."},"shipping":{"type":"object","required":["countries","priceJpy","carrier","transitDays"],"properties":{"countries":{"type":"array","items":{"type":"string"},"description":"ISO 3166-1 alpha-2; Japan only."},"priceJpy":{"type":"integer"},"carrier":{"type":"string"},"transitDays":{"$ref":"#/components/schemas/SizeBand"}}},"cancellation":{"type":"object","properties":{"freeUntilHoursAfterApproval":{"type":"integer"}}},"guarantee":{"type":"object","properties":{"faceYears":{"type":"integer"},"reCarvedIfWardRefuses":{"type":"boolean"},"photographedBeforeDispatch":{"type":"boolean"}}},"seal":{"type":"object","properties":{"bodyLengthMm":{"type":"number"},"reliefMm":{"type":"number"},"defaultSizeMm":{"type":"number"},"defaultMaterial":{"type":"string","enum":["aluminium","titanium"]},"maxNameGraphemes":{"type":"integer"}}},"sizesMm":{"type":"array","items":{"type":"number"},"description":"Every size carved, ascending — the union of both shapes. Not every size is offered in every shape: read `sizesByShape`."},"sizesByShape":{"type":"object","description":"The sizes each silhouette is carved in. A rounded square starts at 15 mm and goes up to the 24 mm 角印; a round seal stops at 18 mm.","properties":{"round":{"type":"array","items":{"type":"number"}},"square":{"type":"array","items":{"type":"number"}}}},"uses":{"type":"array","items":{"$ref":"#/components/schemas/Use"}},"materials":{"type":"array","items":{"$ref":"#/components/schemas/Material"}},"shapes":{"type":"array","items":{"type":"object","required":["id","name","sizesMm"],"properties":{"id":{"type":"string","enum":["round","square"]},"name":{"$ref":"#/components/schemas/Names"},"sizesMm":{"type":"array","items":{"type":"number"}}}}},"families":{"type":"array","items":{"$ref":"#/components/schemas/Family"}},"addons":{"type":"array","items":{"type":"object","required":["id","priceJpy"],"properties":{"id":{"type":"string"},"priceJpy":{"type":"integer"},"fitsMm":{"$ref":"#/components/schemas/SizeBand"}}}},"corporateSet":{"type":"object","properties":{"seals":{"type":"integer"},"aluminiumJpy":{"type":"integer"},"titaniumJpy":{"type":"integer"},"caseJpy":{"type":"integer"},"composition":{"type":"array","description":"The three seals: representative 18 mm round, bank 15 mm round (a different diameter on purpose), invoice 24 mm square — the 角印.","items":{"type":"object","required":["role","family","shape","sizeMm"],"properties":{"role":{"type":"string","enum":["representative","bank","invoice"]},"family":{"type":"string"},"shape":{"type":"string","enum":["round","square"]},"sizeMm":{"type":"number"}}}},"url":{"type":"string","format":"uri"}}},"gifts":{"type":"object","properties":{"tiers":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"priceJpy":{"type":"integer"},"material":{"type":"string"}}}},"occasions":{"type":"array","items":{"type":"string"}},"validMonths":{"type":"integer"},"url":{"type":"string","format":"uri"}}},"links":{"type":"object","additionalProperties":{"type":"string","format":"uri"}}}},"EligibilityReport":{"type":"object","description":"What the geometry itself permits at this size, independent of what the family is sold for.","required":["registration","bank","everyday","corporate","level","reasons","metrics"],"properties":{"registration":{"type":"boolean","description":"Passes the ward-office rules for a registered seal (full name, unbroken rim, stroke floor)."},"bank":{"type":"boolean"},"everyday":{"type":"boolean"},"corporate":{"type":"boolean","description":"Passes as a company representative seal."},"level":{"type":["string","null"],"enum":["registration","bank","everyday",null],"description":"Highest personal use permitted; null when not sellable at all."},"reasons":{"type":"array","description":"Why a use is refused, as machine keys.","items":{"type":"object","required":["key"],"properties":{"key":{"type":"string"},"params":{"type":"object","additionalProperties":{"type":"number"}}}}},"metrics":{"type":"object","properties":{"sizeMm":{"type":"number"},"frameMm":{"type":"number","description":"Rim thickness; 0 without a frame."},"minStrokeMm":{"type":"number","description":"Narrowest carved stroke."},"minCellMm":{"type":"number"},"majorMm":{"type":"number"},"minorMm":{"type":"number"},"charCount":{"type":"integer"},"rimContacts":{"type":"integer"}},"additionalProperties":{"type":"number"}}}},"Design":{"type":"object","required":["family","index","seed","shape","recommendedFor","soldFor","eligibleForUse","eligibility","preview","orderUrl"],"properties":{"family":{"type":"string","enum":["insou","tensho","reisho","kaisho","koin","kaku","wave","vortex"]},"index":{"type":"integer"},"seed":{"type":"integer","description":"Identifies this exact design; pass it to `renderSeal`."},"shape":{"type":"string","enum":["round","square"]},"recommendedFor":{"type":"boolean","description":"This family is the one we recommend for the requested use."},"soldFor":{"type":"array","items":{"type":"string","enum":["bank","registered","everyday","corporate"]}},"eligibleForUse":{"type":"boolean","description":"Sold for the requested use AND the geometry passes it at this size. The one to filter on."},"eligibility":{"$ref":"#/components/schemas/EligibilityReport"},"preview":{"type":"object","required":["svg","json"],"properties":{"svg":{"type":"string","format":"uri","description":"The impression as SVG (`renderSeal`)."},"json":{"type":"string","format":"uri","description":"Geometry + eligibility (`renderSeal` with view=json)."}}},"orderUrl":{"type":"string","format":"uri","description":"Where a person orders exactly this design, size, metal and shape. Hand this to the human."}}},"DesignSheet":{"type":"object","required":["name","use","sizeMm","material","shape","index","priceJpy","currency","pricesIncludeTax","leadDays","designs"],"properties":{"name":{"type":"string"},"use":{"type":"string","enum":["bank","registered","everyday","corporate"]},"sizeMm":{"type":"number"},"material":{"type":"string","enum":["aluminium","titanium"]},"shape":{"type":["string","null"],"enum":["round","square",null],"description":"The forced shape, or null when each design keeps its own."},"index":{"type":"integer"},"priceJpy":{"type":"integer","description":"One seal in this metal for this use, tax included."},"currency":{"type":"string","const":"JPY"},"pricesIncludeTax":{"type":"boolean","const":true},"leadDays":{"type":"integer"},"designs":{"type":"array","items":{"$ref":"#/components/schemas/Design"},"minItems":8,"maxItems":8}}},"SealJson":{"type":"object","required":["face","eligibility"],"properties":{"face":{"type":"object","description":"The carved face for a 3D stage: rings of points in impression units, a scale and a depth.","additionalProperties":true},"eligibility":{"$ref":"#/components/schemas/EligibilityReport"}}}}}}