{"openapi":"3.1.0","info":{"title":"bicycle.guide — guide registry API","version":"1.0.0","description":"The published-guide registry (the control plane of the guide business), its taxonomy, and the capability spine joining books × guides × KSAO elements × jobs — read-only control-plane metadata for cooperating repos and agents. Shared-secret auth on every route (see securitySchemes). The same data is also servable, unauthenticated, over MCP at https://bicycle.guide/mcp. Full contract: https://bicycle.guide/docs (repo docs/GUIDE-REGISTRY-API.md).","contact":{"name":"bicycle.guide","url":"https://bicycle.guide"}},"servers":[{"url":"https://bicycle.guide"}],"tags":[{"name":"guide-registry","description":"The published-guide registry, taxonomy and capability spine."}],"components":{"securitySchemes":{"bicycleGuideSecret":{"type":"apiKey","in":"header","name":"x-bicycle-guide-secret","description":"Authorization: Bearer $BICYCLE_GUIDE_API_SECRET, or the x-bicycle-guide-secret header with the same value. Unset secret ⇒ 503 (fails closed, never open data). Missing/invalid credentials ⇒ 401."}}},"paths":{"/api/v1/guides":{"get":{"operationId":"listGuides","summary":"The guide registry — the control plane of the guide business","description":"Every guide in content/registry/guides.json, decorated with has_artifact / home_domain / home_unrouted / renders_here / domain / agent_readable, filterable by home, status, access, standard, series, category, persona, domain, guide_type, pillar, has_artifact and home_unrouted (all optional, AND-ed). Always returns the full-registry `rollup`, computed over every entry regardless of filters, including the distribution gap (guides homed to a property with no rendering surface).","tags":["guide-registry"],"security":[{"bicycleGuideSecret":[]}],"parameters":[{"name":"home","in":"query","required":false,"description":"Filter by owning property, e.g. jobframe, peopleanalyst, penwright.","schema":{"type":"string"}},{"name":"status","in":"query","required":false,"description":"Filter by status: on | draft.","schema":{"type":"string"}},{"name":"access","in":"query","required":false,"description":"Filter by access: free | gated. Derived from price, never authored — see docs/GUIDE-REGISTRY-API.md.","schema":{"type":"string"}},{"name":"standard","in":"query","required":false,"description":"Filter by standard: bicycle | life-stage | problem-opportunity.","schema":{"type":"string"}},{"name":"series","in":"query","required":false,"description":"Filter by guide series — the operational grouping of guides made to be used together.","schema":{"type":"string"}},{"name":"category","in":"query","required":false,"description":"Filter by subject shelf. Matches the primary category OR a cross-shelf tag.","schema":{"type":"string"}},{"name":"persona","in":"query","required":false,"description":"Filter by the audience a guide serves; a guide can serve several.","schema":{"type":"string"}},{"name":"domain","in":"query","required":false,"description":"Filter by life-domain — the layer above the shelf: work | life | play.","schema":{"type":"string"}},{"name":"guide_type","in":"query","required":false,"description":"Filter by guide class: career | capability | book_profile.","schema":{"type":"string"}},{"name":"pillar","in":"query","required":false,"description":"Only pillars (true) or only spokes (false).","schema":{"type":"boolean"}},{"name":"has_artifact","in":"query","required":false,"description":"Only guides that do / do not have a new-design artifact.","schema":{"type":"boolean"}},{"name":"home_unrouted","in":"query","required":false,"description":"Only guides whose home has no rendering surface at all.","schema":{"type":"boolean"}}],"responses":{"200":{"description":"{ api_version, count, filters, registry_meta, rollup, guides: GuideRecord[] }","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"description":"Invalid or missing credentials."},"503":{"description":"BICYCLE_GUIDE_API_SECRET is not configured, or a generated index the route depends on is missing."}}}},"/api/v1/guides/{slug}":{"get":{"operationId":"getGuide","summary":"One guide's registry row, decorated","description":"One guide by slug, decorated with has_artifact / home_domain / home_unrouted / renders_here / domain / agent_readable — the same decoration `GET /api/v1/guides` applies to every row.","tags":["guide-registry"],"security":[{"bicycleGuideSecret":[]}],"parameters":[{"name":"slug","in":"path","required":true,"description":"The guide slug, e.g. start-a-company.","schema":{"type":"string"}}],"responses":{"200":{"description":"{ api_version, guide: GuideRecord } | { error }","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"description":"Invalid or missing credentials."},"404":{"description":"Unknown value for a required selector (e.g. no such guide slug)."},"503":{"description":"BICYCLE_GUIDE_API_SECRET is not configured, or a generated index the route depends on is missing."}}}},"/api/v1/guides/search":{"get":{"operationId":"searchGuides","summary":"Search guides, or refuse with the nearest owned","description":"Deterministic search over registry taxonomy and the capability spine. A miss is a structured refusal (nearest owned guides, normalized missing topic, acquire_queue suggestions when present), never an empty array. No model call.","tags":["guide-registry"],"security":[{"bicycleGuideSecret":[]}],"parameters":[{"name":"q","in":"query","required":true,"description":"Topic or question in plain language.","schema":{"type":"string"}},{"name":"persona","in":"query","required":false,"description":"Audience filter. Failing it produces a structured refusal.","schema":{"type":"string"}},{"name":"category","in":"query","required":false,"description":"Subject shelf filter. Failing it produces a structured refusal.","schema":{"type":"string"}}],"responses":{"200":{"description":"{ api_version, covered, query, missing_topic, filters, guides[], nearest[], suggest[] }","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"description":"Invalid or missing credentials."},"404":{"description":"Unknown value for a required selector (e.g. no such guide slug)."},"503":{"description":"BICYCLE_GUIDE_API_SECRET is not configured, or a generated index the route depends on is missing."}}}},"/api/v1/guides/{slug}/disagreements":{"get":{"operationId":"listDisagreements","summary":"Cross-book disagreements for one guide — names and provenance only","description":"Each cross_book tension's name, the books on each pole (title, author, library_id), and the guide URL. No passages, guidance, stakes, or decision text. A book profile with no cross-book tension returns an empty list. Unknown slug → 404.","tags":["guide-registry"],"security":[{"bicycleGuideSecret":[]}],"parameters":[{"name":"slug","in":"path","required":true,"description":"The guide slug, e.g. start-a-company.","schema":{"type":"string"}}],"responses":{"200":{"description":"{ api_version, slug, count, disagreements: [{ name, poles, guide_slug, guide_url }] }","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"description":"Invalid or missing credentials."},"404":{"description":"Unknown value for a required selector (e.g. no such guide slug)."},"503":{"description":"BICYCLE_GUIDE_API_SECRET is not configured, or a generated index the route depends on is missing."}}}},"/api/v1/taxonomy":{"get":{"operationId":"getTaxonomy","summary":"The guide program's vocabulary, as data","description":"Every classification axis: domains (work/life/play), shelves with their domain and live guide counts, series, personas, guide_types, the conventions a producing repo must satisfy, and the unclassified counts. Computed over the live registry, so a stale count is impossible. No params.","tags":["guide-registry"],"security":[{"bicycleGuideSecret":[]}],"responses":{"200":{"description":"{ api_version, registry_meta, domains, shelves, series, personas, guide_types, conventions, unclassified }","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"description":"Invalid or missing credentials."},"503":{"description":"BICYCLE_GUIDE_API_SECRET is not configured, or a generated index the route depends on is missing."}}}},"/api/v1/capabilities":{"get":{"operationId":"listCapabilities","summary":"The capability spine — books × guides × KSAO elements × jobs","description":"The join across all four objects: capabilities (guides) × KSAO-grade elements × books, with element→job edges derived from the career-guide role-level convention. Filter elements by min_guides, has_job, role, capability, conflicting, ksao_type, construct_class, has_canon_identity, canon_promotion_candidate, q and limit, or pass capability_detail to return one capability with its elements and books hydrated instead of querying elements.","tags":["guide-registry"],"security":[{"bicycleGuideSecret":[]}],"parameters":[{"name":"min_guides","in":"query","required":false,"description":"Only elements taught by >= N capabilities — the cross-cutting spine.","schema":{"type":"number"}},{"name":"has_job","in":"query","required":false,"description":"Only elements some job requires.","schema":{"type":"boolean"}},{"name":"role","in":"query","required":false,"description":"Elements required by this job role.","schema":{"type":"string"}},{"name":"capability","in":"query","required":false,"description":"Elements taught by this capability (guide slug).","schema":{"type":"string"}},{"name":"conflicting","in":"query","required":false,"description":"Only elements where non-career guides disagree on meaning.","schema":{"type":"boolean"}},{"name":"ksao_type","in":"query","required":false,"description":"knowledge | skill | ability | other, from the validated panel overlay.","schema":{"type":"string"}},{"name":"construct_class","in":"query","required":false,"description":"person-attribute | condition-or-outcome.","schema":{"type":"string"}},{"name":"has_canon_identity","in":"query","required":false,"description":"Only elements resolved to (true) / unresolved against (false) a JobFrame canon component.","schema":{"type":"boolean"}},{"name":"canon_promotion_candidate","in":"query","required":false,"description":"Only elements the canon has no component for — promotion candidates.","schema":{"type":"boolean"}},{"name":"q","in":"query","required":false,"description":"Substring match on the element label.","schema":{"type":"string"}},{"name":"limit","in":"query","required":false,"description":"Cap the rows returned (default 200).","schema":{"type":"number"}},{"name":"capability_detail","in":"query","required":false,"description":"Return one capability with its elements and books hydrated.","schema":{"type":"string"}}],"responses":{"200":{"description":"{ api_version, spine_meta, filters, total, elements[] } | { api_version, spine_meta, capability }","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"description":"Invalid or missing credentials."},"503":{"description":"BICYCLE_GUIDE_API_SECRET is not configured, or a generated index the route depends on is missing."}}}},"/api/v1/conditions":{"get":{"operationId":"listConditions","summary":"Organizational conditions — identity, label, corroboration, causal roles","description":"ConditionFrame identity catalog. Each row is a frozen condition_identity_id with its label, guide corroboration count, and causal-role counts. Filter by draft domain/subdomain slug or causal_role. Domain slugs are draft until BG-180's freeze ceremony; SHAPES addresses are not emitted. Names and counts only — no passages, no capability→condition join.","tags":["guide-registry"],"security":[{"bicycleGuideSecret":[]}],"parameters":[{"name":"id","in":"query","required":false,"description":"Exact condition_identity_id. When set, other filters are ignored.","schema":{"type":"string"}},{"name":"domain","in":"query","required":false,"description":"Draft domain slug, e.g. organizational-structure-and-culture.","schema":{"type":"string"}},{"name":"subdomain","in":"query","required":false,"description":"Draft sub-domain slug, e.g. organizational-learning-and-improvement.","schema":{"type":"string"}},{"name":"causal_role","in":"query","required":false,"description":"driver | mediator | outcome. Unknown values match nothing.","schema":{"type":"string"}},{"name":"q","in":"query","required":false,"description":"Substring match on the condition label.","schema":{"type":"string"}},{"name":"limit","in":"query","required":false,"description":"Cap rows returned. Default 100, max 500.","schema":{"type":"number"}}],"responses":{"200":{"description":"{ api_version, address_status, filters, count, total_matching, taxonomy, conditions[] }","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"description":"Invalid or missing credentials."},"503":{"description":"BICYCLE_GUIDE_API_SECRET is not configured, or a generated index the route depends on is missing."}}}},"/api/v1/membership-interest":{"get":{"operationId":"listMembershipInterest","summary":"Archived membership-interest submissions for operational reconciliation","description":"Read-only protected export of historical interest captures. New cooperative marketing capture is retired; this preserves existing records for reconciliation only.","tags":["guide-registry"],"security":[{"bicycleGuideSecret":[]}],"responses":{"200":{"description":"{ api_version, forwarded, deadLettered, count, counts_by_chapter_and_option, submissions[] }","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"description":"Invalid or missing credentials."},"503":{"description":"BICYCLE_GUIDE_API_SECRET is not configured, or a generated index the route depends on is missing."}}}}}}