{"openapi":"3.1.0","info":{"title":"Lunar Atlas API","version":"v1","description":"Agent-vendor-neutral REST API for the Lunar Atlas catalog. The web UI walks through it. Agents walk through it. Single source of truth for every read and every write. See https://lunaratlas.dev/api for interactive docs.","contact":{"name":"Lunar Rails","url":"https://lunaratlas.dev"}},"servers":[{"url":"https://lunaratlas.dev/api/v1","description":"Production"},{"url":"https://atlas-dev.lunaratlas.dev/api/v1","description":"Isolated staging"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","description":"Atlas Agent API key. Minted by an admin/curator from /dashboard/team. Keys are scoped (read:atlas, read:people, read:proposals, write:proposals, write:discovery-sprints, read:gtm, write:gtm, write:sources), budgeted, revocable, rate-limited, and auditable. GTM and direct-write scopes always require explicit grants."}},"schemas":{"Error":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message","retryable"],"properties":{"code":{"type":"string","enum":["VALIDATION_ERROR","UNAUTHORIZED","FORBIDDEN","NOT_FOUND","CONFLICT","PRECONDITION_REQUIRED","APPROVAL_MISMATCH","RATE_LIMITED","BUDGET_EXHAUSTED","INTERNAL"]},"message":{"type":"string"},"hint":{"type":"string"},"retryable":{"type":"boolean"},"doc_url":{"type":"string","format":"uri"}}}}},"Segment":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"slug":{"type":"string","example":"miners"},"name":{"type":"string","example":"Miners"},"description":{"type":"string","nullable":true},"parent_id":{"type":"string","format":"uuid","nullable":true},"sort_order":{"type":"integer"},"hue_token":{"type":"string","nullable":true},"focus_kind":{"type":"string","enum":["core","context"],"description":"core = one of the four primary Lunar Rails operating segments (Mining, Corporate Treasuries, Lightning, Family Offices); context = supporting ecosystem terrain."}}},"Capability":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"slug":{"type":"string","example":"custody","description":"Stable lowercase slug. Use this value in propose endpoints, never the display name."},"name":{"type":"string","example":"Institutional Custody"},"description":{"type":"string","nullable":true},"horizon":{"type":"string","enum":["now","near","future"],"description":"Default Lunar Rails timeline for this capability. Agents may override per entity via the lr_fit horizon field."},"sort_order":{"type":"integer"}}},"Need":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"slug":{"type":"string"},"name":{"type":"string"},"description":{"type":"string","nullable":true},"primary_capability_id":{"type":"string","format":"uuid","nullable":true}}},"Vertical":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"slug":{"type":"string"},"name":{"type":"string"},"description":{"type":"string","nullable":true},"segment_hint_id":{"type":"string","format":"uuid","nullable":true},"sort_order":{"type":"integer"}}},"TaxonomyTerm":{"type":"object","description":"Stable agent-facing taxonomy term. Use slug values in filters and proposal payloads.","properties":{"id":{"type":"string","format":"uuid"},"slug":{"type":"string","example":"lightning.wallets.custodial"},"name":{"type":"string","example":"Custodial Lightning Wallets"},"description":{"type":"string","nullable":true},"kind":{"type":"string","enum":["segment","subsegment","product_category","capability","protocol","geography","lifecycle","risk","custom"]},"parent_id":{"type":"string","format":"uuid","nullable":true},"sort_order":{"type":"integer"},"status":{"type":"string","enum":["active","deprecated"]},"replaced_by":{"type":"object","nullable":true,"properties":{"id":{"type":"string","format":"uuid"},"slug":{"type":"string"},"name":{"type":"string"}}}}},"FieldEvent":{"type":"object","description":"Event-planning record for conferences, summits, meetups, roadshows, and other field-intel surfaces. Agents with trusted GTM scopes can create events and attach segments, entities, and people.","properties":{"id":{"type":"string","format":"uuid"},"slug":{"type":"string","example":"btc-prague-2026"},"name":{"type":"string","example":"BTC Prague 2026"},"event_kind":{"type":"string","enum":["conference","summit","meetup","side_event","roadshow","webinar","other"]},"starts_at":{"type":"string","format":"date","nullable":true},"ends_at":{"type":"string","format":"date","nullable":true},"city":{"type":"string","nullable":true},"country":{"type":"string","nullable":true},"venue":{"type":"string","nullable":true},"website_url":{"type":"string","format":"uri","nullable":true},"priority":{"type":"string","enum":["must_attend","high","medium","watch","skip"]},"lifecycle_status":{"type":"string","enum":["researching","planning","outreach","booked","attended","follow_up","skipped"]},"strategic_reason":{"type":"string","nullable":true},"outreach_goal":{"type":"string","nullable":true},"notes_md":{"type":"string","nullable":true},"segments":{"type":"array","items":{"type":"object","properties":{"relevance":{"type":"string","nullable":true},"segment":{"$ref":"#/components/schemas/Segment"}}}},"entities":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"role":{"type":"string"},"outreach_status":{"type":"string"},"relationship_note":{"type":"string","nullable":true},"next_step":{"type":"string","nullable":true},"meeting_target":{"type":"boolean"},"entity":{"type":"object","additionalProperties":true}}}},"people":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"role":{"type":"string"},"outreach_status":{"type":"string"},"relationship_note":{"type":"string","nullable":true},"next_step":{"type":"string","nullable":true},"meeting_target":{"type":"boolean"},"person":{"type":"object","additionalProperties":true}}}},"goals":{"type":"array","items":{"$ref":"#/components/schemas/FieldEventGoal"}},"interactions":{"type":"array","items":{"$ref":"#/components/schemas/FieldEventInteraction"}},"followUps":{"type":"array","items":{"$ref":"#/components/schemas/FieldEventFollowUp"}},"scorecard":{"anyOf":[{"$ref":"#/components/schemas/FieldEventScorecard"},{"type":"null"}]},"roster":{"type":"array","items":{"$ref":"#/components/schemas/FieldEventRosterCandidate"},"description":"Agent-discovered roster candidates staged for this event — see the roster endpoints below."},"team_assignments":{"type":"array","description":"Internal team attendance for this event. Read-only over the API: assignments are written through the trusted dashboard, never the public write endpoints. Profile payloads expose id, display_name, and role only — never email.","items":{"type":"object","properties":{"attendance_status":{"type":"string","enum":["attending","should_attend"]},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"},"profile":{"type":"object","nullable":true,"properties":{"id":{"type":"string","format":"uuid"},"display_name":{"type":"string","nullable":true},"role":{"type":"string"}}}}}},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}},"FieldEventInput":{"type":"object","required":["name"],"properties":{"slug":{"type":"string","pattern":"^[a-z0-9][a-z0-9-]*$","example":"btc-prague-2026"},"name":{"type":"string","minLength":2,"maxLength":160},"event_kind":{"type":"string","enum":["conference","summit","meetup","side_event","roadshow","webinar","other"],"default":"conference"},"starts_at":{"type":"string","format":"date","nullable":true},"ends_at":{"type":"string","format":"date","nullable":true},"city":{"type":"string","nullable":true},"country":{"type":"string","nullable":true},"venue":{"type":"string","nullable":true},"website_url":{"type":"string","format":"uri","nullable":true},"priority":{"type":"string","enum":["must_attend","high","medium","watch","skip"],"default":"watch"},"lifecycle_status":{"type":"string","enum":["researching","planning","outreach","booked","attended","follow_up","skipped"],"default":"researching"},"strategic_reason":{"type":"string","nullable":true,"maxLength":2000},"outreach_goal":{"type":"string","nullable":true,"maxLength":1200},"notes_md":{"type":"string","nullable":true,"maxLength":8000}}},"FieldEventEntityLinkInput":{"type":"object","required":["role"],"properties":{"entity_id":{"type":"string","format":"uuid"},"entity_slug":{"type":"string","example":"river-financial"},"role":{"type":"string","enum":["attending","sponsor","speaker","host","side_event_host","target_customer","prospect","partner","competitor","media","other"]},"outreach_status":{"type":"string","enum":["research","to_contact","contacted","meeting_requested","meeting_booked","met","follow_up","no_action"],"default":"research"},"relationship_note":{"type":"string","nullable":true},"next_step":{"type":"string","nullable":true},"meeting_target":{"type":"boolean","default":false}}},"FieldEventPersonLinkInput":{"type":"object","required":["role"],"properties":{"person_id":{"type":"string","format":"uuid"},"person_slug":{"type":"string"},"role":{"type":"string","enum":["attending","speaker","organizer","host","warm_intro","target_contact","relationship_owner","other"]},"outreach_status":{"type":"string","enum":["research","to_contact","contacted","meeting_requested","meeting_booked","met","follow_up","no_action"],"default":"research"},"relationship_note":{"type":"string","nullable":true},"next_step":{"type":"string","nullable":true},"meeting_target":{"type":"boolean","default":false}}},"FieldEventSegmentLinkInput":{"type":"object","properties":{"segment_id":{"type":"string","format":"uuid"},"segment_slug":{"type":"string","example":"lightning"},"relevance":{"type":"string","nullable":true}}},"FieldEventsProposalRequest":{"type":"object","required":["operation","event"],"properties":{"operation":{"type":"string","enum":["create","update"],"description":"Explicit identity intent. update fails if the slug is missing; create fails if it already exists."},"event":{"allOf":[{"$ref":"#/components/schemas/FieldEventInput"},{"type":"object","required":["slug"]}],"description":"The canonical event slug is required for this proposal endpoint; identity is never derived from name."},"segments":{"type":"array","maxItems":20,"items":{"$ref":"#/components/schemas/FieldEventSegmentLinkInput"},"description":"Segments to tag the event with. Each entry needs segment_id or segment_slug."},"entities":{"type":"array","maxItems":100,"items":{"$ref":"#/components/schemas/FieldEventEntityLinkInput"},"description":"Known entities attending/sponsoring/etc. Each entry needs entity_id or entity_slug."},"people":{"type":"array","maxItems":100,"items":{"$ref":"#/components/schemas/FieldEventPersonLinkInput"},"description":"Known people attending/speaking/etc. Each entry needs person_id or person_slug."},"unmatched_entities":{"type":"array","maxItems":100,"items":{"type":"string","maxLength":200},"description":"Free-text entity names the agent couldn't resolve to a catalog entity. Carried for curator review, not auto-created."},"unmatched_people":{"type":"array","maxItems":100,"items":{"type":"string","maxLength":200},"description":"Free-text person names the agent couldn't resolve to a catalog person. Carried for curator review, not auto-created."},"match_rationale":{"type":"string","maxLength":2000,"description":"Why these segments/entities/people were matched to this event."},"sources":{"type":"array","maxItems":20,"description":"Optional evidence URLs carried as evidence_sources on each normalized change.","items":{"type":"object","required":["url"],"properties":{"url":{"type":"string","format":"uri"},"title":{"type":"string","maxLength":200},"trust_tier":{"type":"string","enum":["public","reputable","private","rumor"]},"note":{"type":"string","maxLength":1000}}}},"dry_run":{"type":"boolean","default":false,"description":"When true, validates and returns normalized changes plus an environment-bound approval digest without creating a proposal."}}},"FieldEventProposalDryRunResponse":{"type":"object","required":["valid","dry_run","environment","event_slug","operation","change_count","normalized_changes","approval","approval_digest","submit_endpoint","verify_event_url","inbox_url"],"properties":{"valid":{"type":"boolean"},"dry_run":{"type":"boolean","enum":[true]},"environment":{"type":"string","enum":["production","staging"]},"event_slug":{"type":"string"},"operation":{"type":"string","enum":["create","update"]},"change_count":{"type":"integer"},"change_kinds":{"type":"array","items":{"type":"string"}},"normalized_changes":{"type":"array","items":{"type":"object"}},"approval":{"type":"object"},"approval_digest":{"type":"string","pattern":"^sha256:[a-f0-9]{64}$"},"submit_endpoint":{"type":"string","format":"uri"},"verify_event_url":{"type":"string","format":"uri"},"inbox_url":{"type":"string","format":"uri"}}},"FieldEventGoal":{"type":"object","description":"Structured, trackable outcome for a field event (e.g. \"Book 3 treasury custody meetings\").","properties":{"id":{"type":"string","format":"uuid"},"field_event_id":{"type":"string","format":"uuid"},"title":{"type":"string","example":"Book 3 treasury custody meetings"},"metric":{"type":"string","nullable":true,"example":"Meetings booked"},"target_value":{"type":"number","nullable":true},"progress_value":{"type":"number","nullable":true},"owner_profile_id":{"type":"string","format":"uuid","nullable":true},"status":{"type":"string","enum":["on_track","at_risk","achieved","missed","dropped"]},"due_date":{"type":"string","format":"date","nullable":true},"notes":{"type":"string","nullable":true},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}},"FieldEventGoalInput":{"type":"object","required":["title"],"properties":{"title":{"type":"string","minLength":2,"maxLength":200},"metric":{"type":"string","nullable":true,"maxLength":200},"target_value":{"type":"number","nullable":true},"progress_value":{"type":"number","nullable":true},"status":{"type":"string","enum":["on_track","at_risk","achieved","missed","dropped"],"default":"on_track"},"due_date":{"type":"string","format":"date","nullable":true},"notes":{"type":"string","nullable":true,"maxLength":2000}}},"FieldEventGoalPatchInput":{"type":"object","description":"All fields optional; at least one is required.","properties":{"title":{"type":"string","minLength":2,"maxLength":200},"metric":{"type":"string","nullable":true,"maxLength":200},"target_value":{"type":"number","nullable":true},"progress_value":{"type":"number","nullable":true},"status":{"type":"string","enum":["on_track","at_risk","achieved","missed","dropped"]},"due_date":{"type":"string","format":"date","nullable":true},"notes":{"type":"string","nullable":true,"maxLength":2000}}},"FieldEventInteraction":{"type":"object","description":"One concrete meeting/touchpoint at a field event.","properties":{"id":{"type":"string","format":"uuid"},"field_event_id":{"type":"string","format":"uuid"},"entity_id":{"type":"string","format":"uuid","nullable":true},"person_id":{"type":"string","format":"uuid","nullable":true},"counterpart_name":{"type":"string","nullable":true},"counterpart_context":{"type":"string","nullable":true},"scheduled_at":{"type":"string","format":"date-time","nullable":true},"location":{"type":"string","nullable":true},"purpose":{"type":"string","nullable":true},"owner_profile_id":{"type":"string","format":"uuid","nullable":true},"status":{"type":"string","enum":["planned","booked","completed","missed","cancelled"]},"outcome_notes":{"type":"string","nullable":true},"signal_strength":{"type":"string","enum":["none","weak","moderate","strong"]},"next_step":{"type":"string","nullable":true},"entity":{"type":"object","nullable":true,"additionalProperties":true},"person":{"type":"object","nullable":true,"additionalProperties":true},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}},"FloorCaptureInput":{"type":"object","required":["person_name","what_mattered"],"description":"Hallway dump. person_name and what_mattered are required. Optional person_slug/entity_slug attach an existing Atlas record to the interaction only; omitted dumps stay freeform. Never creates a canonical person or entity.","properties":{"person_name":{"type":"string","minLength":1,"maxLength":160},"org_name":{"type":"string","nullable":true,"maxLength":160},"why":{"type":"string","nullable":true,"maxLength":1000,"description":"Why we talked / hunt why."},"what_mattered":{"type":"string","minLength":1,"maxLength":4000},"ask":{"type":"string","nullable":true,"maxLength":1000,"description":"Next ask. When at least 2 characters, opens a follow-up."},"owner":{"type":"string","nullable":true,"maxLength":200,"description":"Persisted on follow_up.destination and roster.relationship_note."},"due_date":{"type":"string","format":"date","nullable":true},"occurred_at":{"type":"string","format":"date","nullable":true,"description":"Conversation day (YYYY-MM-DD). Defaults to today UTC. Stored as scheduled_at midnight UTC."},"channel":{"type":"string","nullable":true,"maxLength":200,"description":"Stored on interaction.location. Defaults to in-person."},"person_slug":{"type":"string","description":"Optional. Only set person_id when this is passed and resolves."},"entity_slug":{"type":"string","description":"Optional. Only set entity_id when this is passed and resolves."}},"example":{"person_name":"Peng Li","org_name":"Luxor","why":"Hashprice desk","what_mattered":"Wants a clean settlement path for pool payouts.","ask":"Send the pool settlement one-pager","owner":"Grafton","due_date":"2026-08-28","occurred_at":"2026-08-23","channel":"in-person"}},"FloorCaptureResult":{"type":"object","required":["interaction_id","roster_candidate_ids","follow_up_id","slug"],"properties":{"interaction_id":{"type":"string","format":"uuid"},"roster_candidate_ids":{"type":"array","items":{"type":"string","format":"uuid"}},"follow_up_id":{"type":"string","format":"uuid","nullable":true},"slug":{"type":"string"}}},"FieldEventInteractionInput":{"type":"object","description":"One of entity_id/entity_slug, person_id/person_slug, or counterpart_name is required.","properties":{"entity_id":{"type":"string","format":"uuid"},"entity_slug":{"type":"string"},"person_id":{"type":"string","format":"uuid"},"person_slug":{"type":"string"},"counterpart_name":{"type":"string","nullable":true,"maxLength":160},"counterpart_context":{"type":"string","nullable":true,"maxLength":1000},"scheduled_at":{"type":"string","format":"date-time","nullable":true},"location":{"type":"string","nullable":true,"maxLength":200},"purpose":{"type":"string","nullable":true,"maxLength":1000},"status":{"type":"string","enum":["planned","booked","completed","missed","cancelled"],"default":"planned"},"outcome_notes":{"type":"string","nullable":true,"maxLength":4000},"signal_strength":{"type":"string","enum":["none","weak","moderate","strong"],"default":"none"},"next_step":{"type":"string","nullable":true,"maxLength":1000}}},"FieldEventInteractionPatchInput":{"type":"object","description":"All fields optional; at least one is required.","properties":{"entity_id":{"type":"string","format":"uuid","nullable":true},"entity_slug":{"type":"string"},"person_id":{"type":"string","format":"uuid","nullable":true},"person_slug":{"type":"string"},"counterpart_name":{"type":"string","nullable":true,"maxLength":160},"counterpart_context":{"type":"string","nullable":true,"maxLength":1000},"scheduled_at":{"type":"string","format":"date-time","nullable":true},"location":{"type":"string","nullable":true,"maxLength":200},"purpose":{"type":"string","nullable":true,"maxLength":1000},"status":{"type":"string","enum":["planned","booked","completed","missed","cancelled"]},"outcome_notes":{"type":"string","nullable":true,"maxLength":4000},"signal_strength":{"type":"string","enum":["none","weak","moderate","strong"]},"next_step":{"type":"string","nullable":true,"maxLength":1000}}},"FieldEventFollowUp":{"type":"object","description":"Post-meeting or post-event action item. May link back to the interaction it came out of.","properties":{"id":{"type":"string","format":"uuid"},"field_event_id":{"type":"string","format":"uuid"},"interaction_id":{"type":"string","format":"uuid","nullable":true},"entity_id":{"type":"string","format":"uuid","nullable":true},"person_id":{"type":"string","format":"uuid","nullable":true},"owner_profile_id":{"type":"string","format":"uuid","nullable":true},"action_text":{"type":"string"},"follow_up_type":{"type":"string","enum":["email","call","meeting","intro","proposal","internal","other"]},"destination":{"type":"string","nullable":true,"example":"bd@example.com"},"due_date":{"type":"string","format":"date","nullable":true},"status":{"type":"string","enum":["open","in_progress","done","cancelled"]},"completed_at":{"type":"string","format":"date-time","nullable":true},"entity":{"type":"object","nullable":true,"additionalProperties":true},"person":{"type":"object","nullable":true,"additionalProperties":true},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}},"FieldEventFollowUpInput":{"type":"object","required":["action_text"],"properties":{"interaction_id":{"type":"string","format":"uuid","nullable":true},"entity_id":{"type":"string","format":"uuid"},"entity_slug":{"type":"string"},"person_id":{"type":"string","format":"uuid"},"person_slug":{"type":"string"},"action_text":{"type":"string","minLength":2,"maxLength":500},"follow_up_type":{"type":"string","enum":["email","call","meeting","intro","proposal","internal","other"],"default":"other"},"destination":{"type":"string","nullable":true,"maxLength":200},"due_date":{"type":"string","format":"date","nullable":true},"status":{"type":"string","enum":["open","in_progress","done","cancelled"],"default":"open"}}},"FieldEventFollowUpPatchInput":{"type":"object","description":"All fields optional; at least one is required. Setting status to \"done\" without an explicit completed_at stamps completed_at with the current time.","properties":{"entity_id":{"type":"string","format":"uuid","nullable":true},"entity_slug":{"type":"string"},"person_id":{"type":"string","format":"uuid","nullable":true},"person_slug":{"type":"string"},"action_text":{"type":"string","minLength":2,"maxLength":500},"follow_up_type":{"type":"string","enum":["email","call","meeting","intro","proposal","internal","other"]},"destination":{"type":"string","nullable":true,"maxLength":200},"due_date":{"type":"string","format":"date","nullable":true},"status":{"type":"string","enum":["open","in_progress","done","cancelled"]}}},"FieldEventScorecard":{"type":"object","description":"Curator-entered qualitative post-event verdict and 30/90-day review state. Quantitative metrics (goal achievement, meeting completion, signals captured, follow-up completion) are derived on read from goals/interactions/follow-ups elsewhere, never stored here.","properties":{"field_event_id":{"type":"string","format":"uuid"},"verdict":{"type":"string","enum":["strong","mixed","weak","too_early"],"nullable":true},"verdict_notes":{"type":"string","nullable":true},"review_30_completed_at":{"type":"string","format":"date-time","nullable":true},"review_30_notes":{"type":"string","nullable":true},"review_90_completed_at":{"type":"string","format":"date-time","nullable":true},"review_90_notes":{"type":"string","nullable":true},"team_time_hours":{"type":"number","nullable":true},"cost_amount":{"type":"number","nullable":true},"cost_currency":{"type":"string","nullable":true,"example":"USD"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}},"FieldEventScorecardPatchInput":{"type":"object","description":"All fields optional; at least one is required. Upserted — PATCH creates the scorecard row if it doesn't exist yet.","properties":{"verdict":{"type":"string","enum":["strong","mixed","weak","too_early"],"nullable":true},"verdict_notes":{"type":"string","nullable":true,"maxLength":4000},"review_30_completed_at":{"type":"string","format":"date-time","nullable":true},"review_30_notes":{"type":"string","nullable":true,"maxLength":4000},"review_90_completed_at":{"type":"string","format":"date-time","nullable":true},"review_90_notes":{"type":"string","nullable":true,"maxLength":4000},"team_time_hours":{"type":"number","nullable":true},"cost_amount":{"type":"number","nullable":true},"cost_currency":{"type":"string","nullable":true,"maxLength":10}}},"FieldEventRosterCandidate":{"type":"object","description":"Agent-discovered roster candidate for a field event — a sponsor, exhibitor, speaker, organizer, host, media contact, attendee, partner, target, or competitor found while researching the event. Event-scoped staging only; never a canonical entity/person until promoted through /v1/agents/proposals/entity or /v1/agents/proposals/person.","properties":{"id":{"type":"string","format":"uuid"},"field_event_id":{"type":"string","format":"uuid"},"candidate_type":{"type":"string","enum":["entity","person","unknown"]},"role":{"type":"string","enum":["sponsor","exhibitor","speaker","organizer","host","media","attendee","partner","target","competitor","other"]},"display_name":{"type":"string"},"context":{"type":"string","nullable":true,"description":"Organization, title, or other free-text context."},"source_url":{"type":"string","format":"uri","nullable":true},"evidence_note":{"type":"string","nullable":true},"confidence":{"type":"integer","minimum":1,"maximum":5},"review_status":{"type":"string","enum":["unreviewed","matched","promoted","dismissed"]},"matched_entity_id":{"type":"string","format":"uuid","nullable":true},"matched_person_id":{"type":"string","format":"uuid","nullable":true},"matched_entity":{"type":"object","nullable":true,"additionalProperties":true},"matched_person":{"type":"object","nullable":true,"additionalProperties":true},"meeting_target":{"type":"boolean"},"outreach_status":{"type":"string","enum":["research","to_contact","contacted","meeting_requested","meeting_booked","met","follow_up","no_action"]},"relationship_note":{"type":"string","nullable":true},"next_step":{"type":"string","nullable":true},"external_ref":{"type":"string","nullable":true},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}},"FieldEventRosterCandidateInput":{"type":"object","required":["role","display_name"],"properties":{"external_ref":{"type":"string","nullable":true,"maxLength":200,"description":"Optional stable id from the source (e.g. the conference site's own sponsor/speaker slug) for precise re-ingestion matching."},"candidate_type":{"type":"string","enum":["entity","person","unknown"],"default":"unknown"},"role":{"type":"string","enum":["sponsor","exhibitor","speaker","organizer","host","media","attendee","partner","target","competitor","other"]},"display_name":{"type":"string","minLength":1,"maxLength":200},"context":{"type":"string","nullable":true,"maxLength":1000},"source_url":{"type":"string","format":"uri","nullable":true},"evidence_note":{"type":"string","nullable":true,"maxLength":2000,"description":"Why the agent believes this — quote, page section, etc."},"confidence":{"type":"integer","minimum":1,"maximum":5,"default":3},"matched_entity_id":{"type":"string","format":"uuid"},"matched_entity_slug":{"type":"string"},"matched_person_id":{"type":"string","format":"uuid"},"matched_person_slug":{"type":"string"},"meeting_target":{"type":"boolean","default":false},"outreach_status":{"type":"string","enum":["research","to_contact","contacted","meeting_requested","meeting_booked","met","follow_up","no_action"],"default":"research"},"relationship_note":{"type":"string","nullable":true,"maxLength":1000},"next_step":{"type":"string","nullable":true,"maxLength":1000}}},"FieldEventRosterBulkInput":{"type":"object","required":["candidates"],"properties":{"candidates":{"type":"array","minItems":1,"maxItems":200,"items":{"$ref":"#/components/schemas/FieldEventRosterCandidateInput"},"description":"Up to 200 candidates per call. Split larger rosters across multiple POSTs."}}},"FieldEventRosterPatchInput":{"type":"object","description":"All fields optional; at least one is required. Setting matched_entity_id/slug or matched_person_id/slug clears the other match and, unless review_status is also given, auto-advances review_status to \"matched\".","properties":{"role":{"type":"string","enum":["sponsor","exhibitor","speaker","organizer","host","media","attendee","partner","target","competitor","other"]},"display_name":{"type":"string","minLength":1,"maxLength":200},"candidate_type":{"type":"string","enum":["entity","person","unknown"]},"context":{"type":"string","nullable":true,"maxLength":1000},"source_url":{"type":"string","format":"uri","nullable":true},"evidence_note":{"type":"string","nullable":true,"maxLength":2000},"confidence":{"type":"integer","minimum":1,"maximum":5},"review_status":{"type":"string","enum":["unreviewed","matched","promoted","dismissed"]},"matched_entity_id":{"type":"string","format":"uuid","nullable":true},"matched_entity_slug":{"type":"string"},"matched_person_id":{"type":"string","format":"uuid","nullable":true},"matched_person_slug":{"type":"string"},"meeting_target":{"type":"boolean"},"outreach_status":{"type":"string","enum":["research","to_contact","contacted","meeting_requested","meeting_booked","met","follow_up","no_action"]},"relationship_note":{"type":"string","nullable":true,"maxLength":1000},"next_step":{"type":"string","nullable":true,"maxLength":1000}}},"ProposalSummary":{"type":"object","description":"Slim proposal row for list views.","properties":{"id":{"type":"string","format":"uuid"},"source":{"type":"string","enum":["fathom","gmail","voice_memo","manual","agent"]},"source_ref":{"type":"string","nullable":true},"status":{"type":"string","enum":["pending","accepted","rejected","unmatched"]},"target_entity":{"type":"object","nullable":true,"properties":{"id":{"type":"string","format":"uuid"},"slug":{"type":"string"},"name":{"type":"string"}}},"match_confidence":{"type":"integer","nullable":true},"match_rationale":{"type":"string","nullable":true},"change_count":{"type":"integer"},"change_kinds":{"type":"array","items":{"type":"string"},"description":"Distinct change kinds in proposed_changes."},"applied_indices":{"type":"array","items":{"type":"integer"},"description":"Which indices into proposed_changes the curator applied."},"decision_notes":{"type":"string","nullable":true},"reviewed_at":{"type":"string","format":"date-time","nullable":true},"created_at":{"type":"string","format":"date-time"}}},"ProposalDetail":{"allOf":[{"$ref":"#/components/schemas/ProposalSummary"},{"type":"object","properties":{"proposed_changes":{"type":"array","items":{"type":"object"},"description":"Full change payloads. Each item carries a `kind` discriminator plus kind-specific fields."}}}]},"SourceSummary":{"type":"object","description":"A source row backing an entity's Dossier. Audio, decks, transcripts, conversation notes, and public URL references. trust_tier signals how cite-able the source is.","properties":{"id":{"type":"string","format":"uuid"},"external_ref":{"type":"string","nullable":true},"kind":{"type":"string","enum":["transcript","deck","conversation","public_url","research","addendum"]},"title":{"type":"string"},"description":{"type":"string","nullable":true},"trust_tier":{"type":"string","enum":["public","reputable","private","rumor"]},"mime_type":{"type":"string","nullable":true},"size_bytes":{"type":"integer","nullable":true},"url":{"type":"string","nullable":true},"has_file":{"type":"boolean"},"is_referenceable":{"type":"boolean"},"created_at":{"type":"string","format":"date-time"}}},"SegmentBreadcrumb":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"slug":{"type":"string"},"name":{"type":"string"}}},"EntitySegmentMembership":{"type":"object","properties":{"is_primary":{"type":"boolean"},"segment":{"allOf":[{"$ref":"#/components/schemas/SegmentBreadcrumb"}],"description":"The specific segment membership row; child segments can appear here as secondary memberships."},"path":{"type":"array","items":{"$ref":"#/components/schemas/SegmentBreadcrumb"},"description":"Breadcrumb from top-level parent to this segment."},"display_path":{"type":"string","example":"Custody → Collaborative Custody"}}},"EntitySegmentResolution":{"type":"object","description":"Canonical segment resolution for agents and UI: top-level placement, optional child breadcrumb, all memberships, taxonomy terms, and a display path.","properties":{"entity_id":{"type":"string","format":"uuid"},"primary_top_level_segment":{"allOf":[{"$ref":"#/components/schemas/SegmentBreadcrumb"}],"nullable":true},"subsegment_breadcrumb":{"type":"array","items":{"$ref":"#/components/schemas/SegmentBreadcrumb"}},"all_segment_memberships":{"type":"array","items":{"$ref":"#/components/schemas/EntitySegmentMembership"}},"taxonomy_terms":{"type":"array","items":{"type":"object"}},"display_path":{"type":"string","nullable":true,"example":"Custody → Collaborative Custody"}}},"EntitySummary":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"slug":{"type":"string"},"name":{"type":"string"},"ticker":{"type":"string","nullable":true},"country":{"type":"string","nullable":true},"region":{"type":"string","nullable":true},"city":{"type":"string","nullable":true},"is_public":{"type":"boolean"},"posture":{"type":"string","enum":["producer","holder","allocator","service_provider","merchant","institution","infrastructure"],"nullable":true},"competitive_posture":{"type":"string","enum":["incumbent","competitor","partner","complement","whitespace","not_applicable"],"nullable":true},"one_liner":{"type":"string","nullable":true},"logo_url":{"type":"string","nullable":true},"website_url":{"type":"string","nullable":true},"x_url":{"type":"string","nullable":true},"linkedin_url":{"type":"string","nullable":true},"github_url":{"type":"string","nullable":true},"nostr_url":{"type":"string","nullable":true},"crunchbase_url":{"type":"string","nullable":true},"strategic_importance":{"type":"integer","nullable":true},"opportunity_thesis":{"type":"string","nullable":true},"buying_trigger":{"type":"string","nullable":true},"trust_blocker":{"type":"string","nullable":true},"next_action":{"type":"string","nullable":true},"opportunity_owner":{"type":"string","nullable":true},"opportunity_rationale":{"type":"string","nullable":true},"show_opportunity_card":{"type":"boolean","description":"Curator-controlled opt-in for rendering the R2 / Opportunity Card on the entity page."},"relationship_status":{"type":"string","enum":["cold","warm","active","client","alumnus"],"nullable":true},"last_verified_at":{"type":"string","format":"date-time","nullable":true},"updated_at":{"type":"string","format":"date-time"},"created_at":{"type":"string","format":"date-time"},"segment":{"type":"object","nullable":true,"properties":{"slug":{"type":"string"},"name":{"type":"string"}}},"segment_resolution":{"$ref":"#/components/schemas/EntitySegmentResolution"}}},"EntityListResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/EntitySummary"}},"next_cursor":{"type":"string","nullable":true},"total":{"type":"integer","nullable":true}}},"ManagementCoverageEntity":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"slug":{"type":"string"},"name":{"type":"string"},"country":{"type":"string","nullable":true},"region":{"type":"string","nullable":true},"city":{"type":"string","nullable":true},"segment":{"type":"object","nullable":true,"properties":{"slug":{"type":"string"},"name":{"type":"string"}}}}},"ManagementCoverageCheck":{"type":"object","properties":{"kind":{"type":"string","enum":["missing_country","missing_city","missing_key_people","missing_relationship_path","missing_sources"]},"label":{"type":"string"},"complete":{"type":"integer"},"missing":{"type":"integer"},"coverage_pct":{"type":"number"}}},"AgentWorkItem":{"type":"object","properties":{"id":{"type":"string","example":"missing_key_people:river-financial"},"kind":{"type":"string","enum":["missing_country","missing_city","missing_key_people","missing_relationship_path","missing_sources"]},"priority":{"type":"string","enum":["high","medium"]},"entity":{"$ref":"#/components/schemas/ManagementCoverageEntity"},"reason":{"type":"string"},"suggested_endpoint":{"type":"string"},"expected_proposal_kind":{"type":"string"}}},"AgentWorkQueue":{"type":"object","properties":{"slug":{"type":"string","example":"people-gaps"},"name":{"type":"string","example":"Key People Gaps"},"description":{"type":"string"},"kinds":{"type":"array","items":{"type":"string","enum":["missing_country","missing_city","missing_key_people","missing_relationship_path","missing_sources"]}}}},"ManagementCoverage":{"type":"object","properties":{"generated_at":{"type":"string","format":"date-time"},"filters":{"type":"object","properties":{"segment":{"type":"string","nullable":true},"tag":{"type":"string","nullable":true},"include_children":{"type":"boolean"}}},"total_entities":{"type":"integer"},"checks":{"type":"array","items":{"$ref":"#/components/schemas/ManagementCoverageCheck"}},"gaps":{"type":"object","additionalProperties":{"type":"array","items":{"$ref":"#/components/schemas/ManagementCoverageEntity"}}},"work_items":{"type":"array","items":{"$ref":"#/components/schemas/AgentWorkItem"}}}},"ProposalTarget":{"type":"object","description":"Every write endpoint accepts either a UUID or a slug. Provide one. match_rationale is optional human-readable context for the inbox card.","properties":{"target_entity_id":{"type":"string","format":"uuid"},"target_entity_slug":{"type":"string","example":"marathon-digital"},"match_rationale":{"type":"string"}}},"LrFitSuggestion":{"type":"object","required":["capability_slug","horizon","fit_score"],"properties":{"capability_slug":{"type":"string","example":"custody"},"horizon":{"type":"string","enum":["now","near","future","partner"]},"fit_score":{"type":"integer","minimum":1,"maximum":5},"rationale":{"type":"string"}}},"ProviderSuggestion":{"type":"object","required":["capability_slug"],"properties":{"capability_slug":{"type":"string","example":"custody"},"provider_entity_id":{"type":"string","nullable":true},"provider_name":{"type":"string","nullable":true},"confidence":{"type":"integer","minimum":1,"maximum":5},"rationale":{"type":"string"}}},"RelationshipSuggestion":{"type":"object","required":["related_entity_id","relationship_type"],"properties":{"related_entity_id":{"type":"string","description":"UUID or slug of another catalog entity"},"relationship_type":{"type":"string","enum":["custody","liquidity","payment","infra","capital","integration","partnership","adjacency"]},"description":{"type":"string"},"confidence":{"type":"integer","minimum":1,"maximum":5},"rationale":{"type":"string"}}},"EventSuggestion":{"type":"object","required":["occurred_at","event_kind","headline"],"properties":{"occurred_at":{"type":"string","example":"2026-05-12"},"event_kind":{"type":"string","example":"integration_announced"},"headline":{"type":"string","maxLength":200},"body":{"type":"string","nullable":true},"confidence":{"type":"integer","minimum":1,"maximum":5},"rationale":{"type":"string"}}},"LrFitProposalRequest":{"allOf":[{"$ref":"#/components/schemas/ProposalTarget"},{"type":"object","required":["suggestions"],"properties":{"suggestions":{"type":"array","items":{"$ref":"#/components/schemas/LrFitSuggestion"},"minItems":1,"maxItems":10}}}]},"ProvidersProposalRequest":{"allOf":[{"$ref":"#/components/schemas/ProposalTarget"},{"type":"object","required":["suggestions"],"properties":{"suggestions":{"type":"array","items":{"$ref":"#/components/schemas/ProviderSuggestion"},"minItems":1,"maxItems":10}}}]},"RelationshipsProposalRequest":{"allOf":[{"$ref":"#/components/schemas/ProposalTarget"},{"type":"object","required":["suggestions"],"properties":{"suggestions":{"type":"array","items":{"$ref":"#/components/schemas/RelationshipSuggestion"},"minItems":1,"maxItems":10}}}]},"EventsProposalRequest":{"allOf":[{"$ref":"#/components/schemas/ProposalTarget"},{"type":"object","required":["events"],"properties":{"events":{"type":"array","items":{"$ref":"#/components/schemas/EventSuggestion"},"minItems":1,"maxItems":20}}}]},"EntityFieldUpdates":{"type":"object","description":"Curator-reviewed field patch for an existing entity dossier. `scale_patch` merges into the existing entity.scale object instead of replacing it.","minProperties":1,"properties":{"one_liner":{"type":"string","nullable":true},"description":{"type":"string","nullable":true},"logo_url":{"type":"string","nullable":true},"website_url":{"type":"string","nullable":true},"x_url":{"type":"string","nullable":true},"linkedin_url":{"type":"string","nullable":true},"github_url":{"type":"string","nullable":true},"nostr_url":{"type":"string","nullable":true},"crunchbase_url":{"type":"string","nullable":true},"strategic_importance":{"type":"integer","minimum":1,"maximum":5},"show_opportunity_card":{"type":"boolean","description":"Opt in to rendering the entity R2 / Opportunity Card. Leave false for ecosystem-context records."},"scale_patch":{"type":"object","additionalProperties":true,"description":"Sparse patch for page-specific scale facts, e.g. treasury_btc, sovereign_btc, auc_usd_band, lightning_capacity_btc."}}},"BundleChange":{"oneOf":[{"type":"object","required":["kind","capability_slug","horizon","fit_score"],"properties":{"kind":{"type":"string","enum":["suggest_lr_fit"]},"capability_slug":{"type":"string"},"horizon":{"type":"string","enum":["now","near","future","partner"]},"fit_score":{"type":"integer","minimum":1,"maximum":5},"rationale":{"type":"string"}}},{"type":"object","required":["kind","capability_slug"],"properties":{"kind":{"type":"string","enum":["add_provider"]},"capability_slug":{"type":"string"},"provider_entity_id":{"type":"string","nullable":true},"provider_name":{"type":"string","nullable":true},"confidence":{"type":"integer","minimum":1,"maximum":5},"rationale":{"type":"string"}}},{"type":"object","required":["kind","related_entity_id","relationship_type"],"properties":{"kind":{"type":"string","enum":["suggest_relationship"]},"related_entity_id":{"type":"string"},"relationship_type":{"type":"string","enum":["custody","liquidity","payment","infra","capital","integration","partnership","adjacency"]},"description":{"type":"string"},"confidence":{"type":"integer","minimum":1,"maximum":5},"rationale":{"type":"string"}}},{"type":"object","required":["kind","occurred_at","event_kind","headline"],"properties":{"kind":{"type":"string","enum":["add_event"]},"occurred_at":{"type":"string"},"event_kind":{"type":"string"},"headline":{"type":"string"},"body":{"type":"string","nullable":true},"confidence":{"type":"integer","minimum":1,"maximum":5},"rationale":{"type":"string"}}},{"type":"object","required":["kind","field_updates"],"description":"Propose updating reader-facing dossier fields for the existing target entity. Applies only after curator approval.","properties":{"kind":{"type":"string","enum":["update_entity_fields"]},"field_updates":{"$ref":"#/components/schemas/EntityFieldUpdates"},"confidence":{"type":"integer","minimum":1,"maximum":5},"rationale":{"type":"string"}}},{"type":"object","required":["kind","append_text"],"properties":{"kind":{"type":"string","enum":["update_notes"]},"append_text":{"type":"string"},"confidence":{"type":"integer","minimum":1,"maximum":5},"rationale":{"type":"string"}}},{"type":"object","required":["kind","status"],"properties":{"kind":{"type":"string","enum":["set_relationship_status"]},"status":{"type":"string","enum":["cold","warm","active","client","alumnus"]},"confidence":{"type":"integer","minimum":1,"maximum":5},"rationale":{"type":"string"}}},{"type":"object","required":["kind","person"],"description":"Propose a new key person. In the same bundle, attach_person_role may reference this new person by person.slug.","properties":{"kind":{"type":"string","enum":["create_person"]},"person":{"type":"object","required":["slug","name"],"properties":{"slug":{"type":"string","pattern":"^[a-z0-9-]+$"},"name":{"type":"string"},"aliases":{"type":"array","items":{"type":"string"}},"country":{"type":"string","nullable":true},"city":{"type":"string","nullable":true},"bio_md":{"type":"string","nullable":true},"avatar_url":{"type":"string","nullable":true},"website_url":{"type":"string","nullable":true},"x_url":{"type":"string","nullable":true},"linkedin_url":{"type":"string","nullable":true},"github_url":{"type":"string","nullable":true},"nostr_url":{"type":"string","nullable":true},"posture_toward_lr":{"type":"string","nullable":true,"description":"Short useful context: why this person matters to Lunar Rails."},"importance_score":{"type":"integer","minimum":1,"maximum":5},"notes":{"type":"string","nullable":true}}},"confidence":{"type":"integer","minimum":1,"maximum":5},"rationale":{"type":"string"}}},{"type":"object","required":["kind","target_person_slug_or_id","person"],"description":"Propose updates to an existing person. Curator-only fields like next_action and trust_blocker are intentionally not accepted from agents.","properties":{"kind":{"type":"string","enum":["update_person"]},"target_person_slug_or_id":{"type":"string"},"person":{"type":"object","properties":{"name":{"type":"string"},"aliases":{"type":"array","items":{"type":"string"}},"country":{"type":"string","nullable":true},"city":{"type":"string","nullable":true},"bio_md":{"type":"string","nullable":true},"avatar_url":{"type":"string","nullable":true},"website_url":{"type":"string","nullable":true},"x_url":{"type":"string","nullable":true},"linkedin_url":{"type":"string","nullable":true},"github_url":{"type":"string","nullable":true},"nostr_url":{"type":"string","nullable":true},"posture_toward_lr":{"type":"string","nullable":true},"importance_score":{"type":"integer","minimum":1,"maximum":5},"notes":{"type":"string","nullable":true}}},"confidence":{"type":"integer","minimum":1,"maximum":5},"rationale":{"type":"string"}}},{"type":"object","required":["kind","taxonomy_term_slug"],"description":"Propose assigning the target entity to an agent-facing taxonomy term such as lightning.wallets.custodial.","properties":{"kind":{"type":"string","enum":["assign_taxonomy_term"]},"taxonomy_term_slug":{"type":"string","example":"lightning.wallets.custodial"},"confidence":{"type":"integer","minimum":1,"maximum":5},"rationale":{"type":"string"}}},{"type":"object","required":["kind","segment_slug"],"description":"Propose moving the target entity into a primary segment, optionally with a subsegment. Use GET /segments first; if the segment doesn't exist, propose it via POST /agents/proposals/segments.","properties":{"kind":{"type":"string","enum":["update_entity_segment"]},"segment_slug":{"type":"string","example":"self-custody-wallets"},"subsegment_slug":{"type":"string","nullable":true},"confidence":{"type":"integer","minimum":1,"maximum":5},"rationale":{"type":"string"}}},{"type":"object","required":["kind","lifecycle_status","reason"],"description":"Recommend a curator-reviewed lifecycle change for the target entity. Agents cannot delete entities; use false_positive or archived to recommend removal from active Atlas surfaces, or defunct for out-of-business entities.","properties":{"kind":{"type":"string","enum":["suggest_entity_lifecycle"]},"lifecycle_status":{"type":"string","enum":["active","defunct","archived","false_positive"]},"reason":{"type":"string"},"confidence":{"type":"integer","minimum":1,"maximum":5},"rationale":{"type":"string"}}},{"type":"object","required":["kind"],"description":"Propose explicit opportunity fields for the target entity. The curator accepts these before they become canonical. Include at least one field; use opportunity_rationale for the source-backed reasoning behind the proposed read.","properties":{"kind":{"type":"string","enum":["suggest_entity_opportunity"]},"opportunity_thesis":{"type":"string","nullable":true},"buying_trigger":{"type":"string","nullable":true},"trust_blocker":{"type":"string","nullable":true},"next_action":{"type":"string","nullable":true},"opportunity_owner":{"type":"string","nullable":true},"opportunity_rationale":{"type":"string","nullable":true},"confidence":{"type":"integer","minimum":1,"maximum":5},"rationale":{"type":"string"}}},{"type":"object","required":["kind","person_slug_or_id","role_kind"],"description":"Attach an existing or same-bundle-created person to the bundle target entity as a key person.","properties":{"kind":{"type":"string","enum":["attach_person_role"]},"person_slug_or_id":{"type":"string","description":"Existing person slug/UUID, or the slug from a create_person change in this same bundle."},"role_kind":{"type":"string","enum":["founder","ceo","cfo","head_of_treasury","board","investor","advisor","employee","ex_employee","partner_contact"]},"role_label":{"type":"string","nullable":true},"is_primary":{"type":"boolean"},"start_date":{"type":"string","format":"date","nullable":true},"end_date":{"type":"string","format":"date","nullable":true},"confidence":{"type":"integer","minimum":1,"maximum":5},"rationale":{"type":"string"}}},{"type":"object","required":["kind","person_slug_or_id","touchpoint_kind"],"description":"Log a person-level touch on the same inbox card as the rest of the bundle. On curator accept, inserts a person_touchpoints row. person_slug_or_id may be an existing person or a create_person slug from this same bundle. Pair with gtm_upsert_assignment so a discovery call lands as one GTM-native card (who we touched, last_touch, call_job, next_validation).","properties":{"kind":{"type":"string","enum":["log_person_touchpoint"]},"person_slug_or_id":{"type":"string","description":"Existing person slug/UUID, or the slug from a create_person change in this same bundle."},"occurred_at":{"type":"string","format":"date","nullable":true,"description":"Day-level YYYY-MM-DD. Use the call date for a discovery call."},"touchpoint_kind":{"type":"string","enum":["call","meeting","email","message","warm-intro","conference","other"]},"channel":{"type":"string","nullable":true,"enum":["telegram","signal","whatsapp","email","phone","linkedin","in-person","other"]},"label":{"type":"string","nullable":true,"maxLength":200},"detail":{"type":"string","nullable":true,"maxLength":20000},"next_step":{"type":"string","nullable":true,"maxLength":500},"next_step_due_at":{"type":"string","format":"date","nullable":true},"confidence":{"type":"integer","minimum":1,"maximum":5},"rationale":{"type":"string"}}},{"type":"object","required":["kind","segment_slug"],"description":"Add or curate a GTM board account. Applies to gtm_entity_assignments on curator accept, only setting the fields you send (never wipes existing data). HONESTY GUARD: setting `stage` (moving into the In-motion surface) REQUIRES `source_ref` — real contact evidence. Omit `stage` for research/watchlist adds. For discovery calls, set last_touch to a parseable day-level string, plus call_job and next_validation, and pair with log_person_touchpoint on the same bundle.","properties":{"kind":{"type":"string","enum":["gtm_upsert_assignment"]},"segment_slug":{"type":"string","example":"mining","description":"GET /v1/gtm/segments for valid slugs."},"lane":{"type":"string","enum":["primary","secondary","watching"]},"stage":{"type":"string","nullable":true,"enum":["spoken-to","booked","introduced","follow-up","handoff"]},"handoff_state":{"type":"string","nullable":true,"enum":["ecosystem","needs-right-person","bd-handoff","product-follow-up","serviceability-review","nurture","pause"]},"classification":{"type":"string","nullable":true,"enum":["bd-ready","product-discovery","watchlist","not-relevant"]},"outreach_status":{"type":"string","enum":["not-contacted","reach-out-next","reached-out","replied"]},"owner":{"type":"string","nullable":true,"description":"Account Owner — the teammate accountable for moving this GTM assignment."},"commercial_weight":{"type":"string","nullable":true,"enum":["shrimp","fish","shark","whale"],"description":"Commercial Size shown on the GTM overview."},"learned":{"type":"string","nullable":true},"next_step":{"type":"string","nullable":true},"needs":{"type":"array","items":{"type":"string","enum":["kevin","tom","product","compliance"]},"nullable":true},"pillars":{"type":"object","nullable":true,"additionalProperties":{"type":"string","enum":["confirmed","hypothesized","not-relevant","asked-unanswered","unknown"]},"description":"Per-pillar GTM signal from a call/intel source, e.g. trading: confirmed, payments: hypothesized, yield: not-relevant."},"product_signal":{"type":"object","nullable":true,"properties":{"area":{"type":"string","description":"Service/product area, e.g. trading, payments, treasury, yield, access-to-capital-markets."},"insight":{"type":"string","description":"Concrete need, pain, workflow, product gap, or serviceability implication."}}},"service_lane":{"type":"string","nullable":true},"contact_path":{"type":"string","nullable":true},"active_channel":{"type":"string","nullable":true},"right_next_person":{"type":"string","nullable":true},"blocker":{"type":"string","nullable":true},"contact_origin":{"type":"string","nullable":true,"enum":["linkedin","conference","event","warm-intro","referral","personal","inbound","cold-outreach","other"]},"contact_origin_detail":{"type":"string","nullable":true},"comms_channel":{"type":"string","nullable":true,"enum":["email","signal","telegram","whatsapp","phone","linkedin","in-person","other"]},"client_for":{"type":"string","nullable":true,"description":"Potential client opportunity — what we could sell them."},"partner_for":{"type":"string","nullable":true,"description":"Potential partner opportunity — what we could partner on."},"source_ref":{"type":"object","nullable":true,"properties":{"label":{"type":"string"},"href":{"type":"string"}}},"last_touch":{"type":"string","nullable":true,"description":"Day-level TEXT (typically YYYY-MM-DD) that Date.parse/parseTouchDate can read so Quiet/Live work. Empty is valid when unsupported."},"call_job":{"type":"string","nullable":true,"description":"Concrete use for the next call. Never generic liquidity or OTC. Empty is valid."},"next_validation":{"type":"string","nullable":true,"description":"One question to answer in the next 30 minutes of the next call. Empty is valid."},"call_workflow":{"type":"string","nullable":true},"call_cost":{"type":"string","nullable":true},"call_architecture":{"type":"string","nullable":true},"call_controls":{"type":"string","nullable":true},"call_evidence":{"type":"string","nullable":true},"call_unknowns":{"type":"string","nullable":true},"mark_live_until":{"type":"string","format":"date-time","nullable":true,"description":"Curator override expiry for Live this week. Not a sticky boolean. Do not invent on a Fathom extract."},"quiet_held_at":{"type":"string","format":"date-time","nullable":true,"description":"Curator Quiet hold. Do not invent on a Fathom extract."},"unreachable_reason":{"type":"string","nullable":true,"description":"Non-null marks the account unreachable for BD (e.g. Tether-owned); other reachability buckets derive from outreach evidence."},"sizing":{"type":"object","nullable":true,"description":"The entity's own estimated revenue (market size) plus scale: hashrate/capacity and share of its own vertical market. Revenue is from monthly Bitcoin production by vertical; method states how the number was made.","properties":{"est_monthly_revenue_btc":{"type":"number"},"est_annual_revenue_usd":{"type":"integer"},"est_monthly_volume_usd":{"type":"integer"},"method":{"type":"string"},"hashrate_eh":{"type":"number","description":"Installed/operated hashrate, EH/s."},"capacity_mw":{"type":"number","description":"Capacity in MW, for hosting/infra."},"market_share_pct":{"type":"number","description":"Share of its vertical market (0-100)."},"market_label":{"type":"string","description":"What the share is of, e.g. 'network hashrate', 'firmware market'."}}},"confidence":{"type":"integer","minimum":1,"maximum":5},"rationale":{"type":"string"}}},{"type":"object","required":["kind"],"description":"Rename the bundle target entity's slug and/or display name. At least one of new_slug/new_name is required. There is no direct rename endpoint — this only ever lands as a curator-reviewed proposal, never auto-accepted, and applying it folds the old slug/name into `aliases` so old references keep resolving.","properties":{"kind":{"type":"string","enum":["rename_entity"]},"new_slug":{"type":"string","minLength":2,"pattern":"^[a-z0-9-]+$","description":"New slug, lowercase letters/digits/dashes only. Rejected up front if another entity already has it."},"new_name":{"type":"string","minLength":1,"maxLength":200},"confidence":{"type":"integer","minimum":1,"maximum":5},"rationale":{"type":"string","maxLength":2000}}},{"type":"object","required":["kind","target_person_slug_or_id"],"description":"Rename a person's slug and/or display name. At least one of new_slug/new_name is required. Curator-reviewed only; the old slug/name fold into `aliases` on accept.","properties":{"kind":{"type":"string","enum":["rename_person"]},"target_person_slug_or_id":{"type":"string","description":"Existing person slug or UUID to rename."},"new_slug":{"type":"string","minLength":2,"pattern":"^[a-z0-9-]+$","description":"New slug, lowercase letters/digits/dashes only. Rejected up front if another person already has it."},"new_name":{"type":"string","minLength":1,"maxLength":200},"confidence":{"type":"integer","minimum":1,"maximum":5},"rationale":{"type":"string","maxLength":2000}}},{"type":"object","required":["kind","duplicate_entity_id"],"description":"Merge a duplicate entity into the bundle's target entity (the target is always the survivor). duplicate_entity_id accepts a UUID or slug. On curator accept, every foreign key referencing the duplicate is repointed to the target inside one transaction, the duplicate's slug/name fold into the target's aliases, and the duplicate is archived with merged_into_id set — never hard-deleted. Irreversible in practice; never bulk-auto-accepted.","properties":{"kind":{"type":"string","enum":["merge_entities"]},"duplicate_entity_id":{"type":"string","description":"The entity to absorb into the bundle target. UUID or slug."},"confidence":{"type":"integer","minimum":1,"maximum":5},"rationale":{"type":"string","maxLength":2000}}},{"type":"object","required":["kind","primary_person_slug_or_id","duplicate_person_slug_or_id"],"description":"Merge duplicate_person into primary_person (primary always survives). Both accept a UUID or slug and must differ. Same reference-safe merge_records() mechanics as merge_entities: FK repoint, alias fold-in, archive-with-redirect. Irreversible in practice; never bulk-auto-accepted.","properties":{"kind":{"type":"string","enum":["merge_people"]},"primary_person_slug_or_id":{"type":"string","description":"The surviving person. UUID or slug."},"duplicate_person_slug_or_id":{"type":"string","description":"The person to absorb into primary. UUID or slug."},"confidence":{"type":"integer","minimum":1,"maximum":5},"rationale":{"type":"string","maxLength":2000}}},{"type":"object","required":["kind","reason"],"description":"Soft-delete the bundle target entity: sets lifecycle_status='archived' with a reason. Agents cannot hard-delete; this only archives (same lifecycle_status column suggest_entity_lifecycle uses). Never bulk-auto-accepted.","properties":{"kind":{"type":"string","enum":["soft_delete_entity"]},"reason":{"type":"string","minLength":1,"maxLength":2000},"confidence":{"type":"integer","minimum":1,"maximum":5},"rationale":{"type":"string","maxLength":2000}}},{"type":"object","required":["kind","target_person_slug_or_id","reason"],"description":"Soft-delete a person: sets lifecycle_status='archived' with a reason. Agents cannot hard-delete; this only archives. Never bulk-auto-accepted.","properties":{"kind":{"type":"string","enum":["soft_delete_person"]},"target_person_slug_or_id":{"type":"string","description":"Existing person slug or UUID to archive."},"reason":{"type":"string","minLength":1,"maxLength":2000},"confidence":{"type":"integer","minimum":1,"maximum":5},"rationale":{"type":"string","maxLength":2000}}}],"discriminator":{"propertyName":"kind"}},"BundleProposalRequest":{"allOf":[{"$ref":"#/components/schemas/ProposalTarget"},{"type":"object","required":["changes"],"properties":{"changes":{"type":"array","items":{"$ref":"#/components/schemas/BundleChange"},"minItems":1,"maxItems":30},"sources":{"type":"array","maxItems":20,"description":"Optional evidence URLs carried with the proposal as evidence_sources on each normalized change. These do not directly create canonical source rows.","items":{"type":"object","required":["url"],"properties":{"url":{"type":"string","format":"uri"},"title":{"type":"string"},"trust_tier":{"type":"string","enum":["public","reputable","private","rumor"]},"note":{"type":"string"}}}}}}],"examples":[{"target_entity_slug":"river-financial","match_rationale":"Research found a relevant partnerships contact.","changes":[{"kind":"create_person","person":{"slug":"jane-doe","name":"Jane Doe","posture_toward_lr":"Owns partner evaluation for Lightning vendors.","importance_score":4},"confidence":4,"rationale":"Named in official River partnerships materials."},{"kind":"attach_person_role","person_slug_or_id":"jane-doe","role_kind":"partner_contact","role_label":"VP Partnerships · possible warm path","is_primary":true,"confidence":4,"rationale":"Relevant contact for a Lunar Rails intro path."}]}]},"EntityProposalRequest":{"type":"object","required":["entity"],"properties":{"entity":{"type":"object","required":["slug","name","segment_slug"],"properties":{"slug":{"type":"string","pattern":"^[a-z0-9-]+$","description":"Lowercase letters, digits, dashes only.","example":"anchorage-digital"},"name":{"type":"string","example":"Anchorage Digital"},"segment_slug":{"type":"string","description":"Must be a slug from GET /v1/segments.","example":"custody"},"subsegment_slug":{"type":"string","nullable":true},"ticker":{"type":"string","nullable":true},"country":{"type":"string","nullable":true},"region":{"type":"string","nullable":true},"city":{"type":"string","nullable":true},"is_public":{"type":"boolean"},"posture":{"type":"string","enum":["producer","holder","allocator","service_provider","merchant","institution","infrastructure"]},"competitive_posture":{"type":"string","enum":["incumbent","competitor","partner","complement","whitespace","not_applicable"]},"one_liner":{"type":"string","nullable":true},"description":{"type":"string","nullable":true},"logo_url":{"type":"string","nullable":true},"website_url":{"type":"string","nullable":true},"x_url":{"type":"string","nullable":true},"linkedin_url":{"type":"string","nullable":true},"github_url":{"type":"string","nullable":true},"nostr_url":{"type":"string","nullable":true},"crunchbase_url":{"type":"string","nullable":true},"aliases":{"type":"array","items":{"type":"string"}},"rationale":{"type":"string"}}},"match_rationale":{"type":"string"},"enrichment":{"type":"object","description":"Optional bundled enrichments that apply to the just-created entity after the curator accepts.","properties":{"lr_fit":{"type":"array","items":{"$ref":"#/components/schemas/LrFitSuggestion"},"maxItems":10},"providers":{"type":"array","items":{"$ref":"#/components/schemas/ProviderSuggestion"},"maxItems":10},"events":{"type":"array","items":{"$ref":"#/components/schemas/EventSuggestion"},"maxItems":20}}}}},"DrilldownEntity":{"type":"object","description":"Entity row shaped for Atlas drill-down pages and agent curation queues.","properties":{"id":{"type":"string","format":"uuid"},"slug":{"type":"string"},"name":{"type":"string"},"ticker":{"type":"string","nullable":true},"country":{"type":"string","nullable":true},"is_public":{"type":"boolean"},"posture":{"type":"string","nullable":true},"competitive_posture":{"type":"string","nullable":true},"one_liner":{"type":"string","nullable":true},"strategic_importance":{"type":"integer","minimum":1,"maximum":5},"relationship_status":{"type":"string"},"scale":{"type":"object","additionalProperties":true},"primary_in_segment":{"type":"boolean"},"matched_segment_paths":{"type":"array","items":{"type":"string"},"description":"Segment paths that caused this entity to match the drilldown request, including child matches when include_children=true."},"segment_resolution":{"$ref":"#/components/schemas/EntitySegmentResolution"},"last_verified_at":{"type":"string","format":"date-time","nullable":true},"updated_at":{"type":"string","format":"date-time"},"dossier_url":{"type":"string","example":"/entities/strategy"},"agent_dossier_endpoint":{"type":"string"},"lr_fit":{"type":"array","items":{"type":"object","properties":{"horizon":{"type":"string"},"fit_score":{"type":"integer","nullable":true}}}},"verticals":{"type":"array","items":{"type":"object"}}}},"DrilldownResponse":{"type":"object","properties":{"segment":{"$ref":"#/components/schemas/Segment"},"stats":{"type":"object","properties":{"total_entities":{"type":"integer"},"primary_targets":{"type":"integer"},"clients":{"type":"integer"},"strategic_4_plus":{"type":"integer"},"with_lr_fit":{"type":"integer"}}},"entities":{"type":"array","items":{"$ref":"#/components/schemas/DrilldownEntity"}},"curation_gaps":{"type":"object","properties":{"missing_one_liner":{"type":"array","items":{"type":"object"}},"missing_lr_fit":{"type":"array","items":{"type":"object"}},"unverified":{"type":"array","items":{"type":"object"}}}},"next_cursor":{"type":"string","nullable":true}}},"DrilldownProposalRequest":{"type":"object","required":["changes"],"properties":{"target_entity_id":{"type":"string","description":"Target entity UUID. Either this or target_entity_slug is required."},"target_entity_slug":{"type":"string","description":"Target entity slug. Either this or target_entity_id is required."},"intent":{"type":"string","enum":["fill_gap","update_scale","improve_dossier_summary","classify_target","other"]},"match_rationale":{"type":"string"},"changes":{"type":"array","minItems":1,"maxItems":10,"items":{"oneOf":[{"type":"object","required":["kind","field_updates"],"properties":{"kind":{"type":"string","enum":["update_entity_fields"]},"field_updates":{"$ref":"#/components/schemas/EntityFieldUpdates"},"confidence":{"type":"integer","minimum":1,"maximum":5},"rationale":{"type":"string"}}},{"type":"object","required":["kind","append_text"],"properties":{"kind":{"type":"string","enum":["update_notes"]},"append_text":{"type":"string"},"confidence":{"type":"integer","minimum":1,"maximum":5},"rationale":{"type":"string"}}},{"type":"object","required":["kind","status"],"properties":{"kind":{"type":"string","enum":["set_relationship_status"]},"status":{"type":"string","enum":["cold","warm","active","client","alumnus"]},"confidence":{"type":"integer","minimum":1,"maximum":5},"rationale":{"type":"string"}}}],"discriminator":{"propertyName":"kind"}}}},"examples":[{"target_entity_slug":"strategy","intent":"update_scale","match_rationale":"Treasury drill-down showed stale holdings metadata.","changes":[{"kind":"update_entity_fields","field_updates":{"scale_patch":{"treasury_btc":582000},"strategic_importance":5},"confidence":4,"rationale":"Public filings and treasury tracker show current BTC holdings."}]}]},"ProposalCreatedResponse":{"type":"object","properties":{"proposal_id":{"type":"string","format":"uuid"},"change_count":{"type":"integer"},"change_kinds":{"type":"array","items":{"type":"string"}},"replayed":{"type":"boolean"},"environment":{"type":"string","enum":["production","staging"]},"approval_digest":{"type":"string","pattern":"^sha256:[a-f0-9]{64}$"},"target_entity":{"type":"object"},"match_rationale":{"type":"string"},"sources_received":{"type":"integer"},"warnings":{"type":"array","items":{"type":"string"}},"inbox_url":{"type":"string","format":"uri"},"status_url":{"type":"string","format":"uri"}}},"GtmAssignmentOverview":{"type":"object","description":"Convenience projection for the six fields shown in the collapsed GTM account row. It does not persist duplicate values: client_name and jurisdiction come from the canonical entity, client_type comes from the assigned GTM segment, and the remaining fields come from the assignment.","required":["client_name","client_type","account_owner","opportunity","jurisdiction","size"],"properties":{"client_name":{"type":"string","nullable":true,"description":"Canonical entity name. Propose changes with rename_entity; the GTM assignment never stores a duplicate name."},"client_type":{"type":"string","nullable":true,"description":"Assigned GTM segment short name. Set it by choosing segment_slug or segment_id on the assignment."},"account_owner":{"type":"string","nullable":true,"description":"Teammate accountable for moving this GTM assignment forward."},"opportunity":{"type":"object","required":["client_for","partner_for"],"properties":{"client_for":{"type":"string","nullable":true},"partner_for":{"type":"string","nullable":true}}},"jurisdiction":{"type":"string","nullable":true,"description":"Canonical entity country. Propose changes through update_entity_fields.country; it is not duplicated on the assignment."},"size":{"type":"string","nullable":true,"enum":["shrimp","fish","shark","whale"],"description":"Curator-assigned commercial weight."}}}},"parameters":{"LimitParam":{"name":"limit","in":"query","description":"Page size. Default 50, max 200.","schema":{"type":"integer","minimum":1,"maximum":200,"default":50}},"CursorParam":{"name":"cursor","in":"query","description":"Opaque cursor from a previous response's `next_cursor`. Omit on the first page.","schema":{"type":"string"}},"IdempotencyKey":{"name":"Idempotency-Key","in":"header","description":"Optional UUID/opaque key. The server caches the response for 24 hours; replays of the same key return the cached proposal_id instead of creating a duplicate.","schema":{"type":"string"}},"RequiredBundleIdempotencyKey":{"name":"Idempotency-Key","in":"header","required":true,"description":"Required opaque retry key for an approved bundle. It is permanently scoped to the active environment, agent identity, endpoint, and approved payload. Reusing it with a different payload returns 409.","schema":{"type":"string","minLength":1,"maxLength":200}},"BundleApprovalDigest":{"name":"X-Atlas-Approval-Digest","in":"header","required":true,"description":"Exact sha256 digest returned by POST /agents/validate/bundle for the approved environment, target, match rationale, normalized changes, and warnings. The submit route re-normalizes against live data and rejects drift.","schema":{"type":"string","pattern":"^sha256:[a-f0-9]{64}$"}}},"responses":{"Unauthorized":{"description":"Missing or invalid bearer token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Forbidden":{"description":"Bearer token is valid but missing the required scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"ValidationError":{"description":"A query parameter or body field is invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"NotFound":{"description":"The referenced resource does not exist.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Conflict":{"description":"The requested write conflicts with an existing resource.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"ProposalCreated":{"description":"Proposal created and queued in the inbox.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProposalCreatedResponse"}}}},"ProposalReplayed":{"description":"An earlier request with the same Idempotency-Key already created this proposal. The cached proposal_id is returned.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProposalCreatedResponse"}}}}}},"paths":{"/whoami":{"get":{"summary":"Identify the calling agent","description":"Returns the calling identity, scopes, and budget. Call this on agent startup to confirm credentials.","responses":{"200":{"description":"Identity payload.","content":{"application/json":{"schema":{"type":"object","properties":{"profile_id":{"type":"string","format":"uuid"},"display_name":{"type":"string"},"role":{"type":"string"},"scopes":{"type":"array","items":{"type":"string","enum":["read:atlas","read:catalog","read:people","read:proposals","write:proposals","write:discovery-sprints","read:gtm","write:gtm","write:sources"]}},"budget":{"type":"object"},"api_version":{"type":"string"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"}}}},"/usage":{"get":{"summary":"Current period's API usage","description":"Returns call count and cost for the current period. Phase A returns placeholders; Phase C wires real per-key tracking.","responses":{"200":{"description":"Usage payload.","content":{"application/json":{"schema":{"type":"object","properties":{"profile_id":{"type":"string","format":"uuid"},"period":{"type":"object"},"calls":{"type":"integer","nullable":true},"cost_usd":{"type":"number","nullable":true}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"}}}},"/gtm/segments":{"get":{"summary":"List GTM operating segments","description":"Returns the GTM focus segments. Pass include_assignments=true to include active/parked entity assignments grouped under each segment, including the six-field overview projection, GTM operating fields, and the effective funnel_stage (funnel_stage_override when pinned, else derived).","responses":{"200":{"description":"GTM segment list."},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"}}}},"/gtm/assignments":{"get":{"summary":"List GTM entity assignments","description":"Filter by entity slug/id, segment slug/id, lane, status, stage, classification, handoff_state, needs, top_prospect, relationship_freshness, or effective funnel_stage. Defaults to non-removed assignments. Each result includes an overview projection with Client name, Client type, Account Owner, Opportunity, Jurisdiction, and Size, plus the full GTM operating shape, funnel_stage/funnel_stage_label, and the 7-day relationship clock (relationship_freshness, last_event_at, mark_live_until, quiet_held_at). Canonical entity name/country stay on the entity; the projection does not duplicate them in storage.","parameters":[{"name":"entity","in":"query","schema":{"type":"string"}},{"name":"segment","in":"query","schema":{"type":"string"}},{"name":"lane","in":"query","schema":{"type":"string","enum":["primary","secondary","watching"]}},{"name":"status","in":"query","schema":{"type":"string","enum":["active","parked","removed"]}},{"name":"stage","in":"query","schema":{"type":"string","enum":["spoken-to","booked","introduced","follow-up","handoff","none"]}},{"name":"classification","in":"query","schema":{"type":"string","enum":["bd-ready","product-discovery","watchlist","not-relevant"]}},{"name":"handoff_state","in":"query","schema":{"type":"string","enum":["ecosystem","needs-right-person","bd-handoff","product-follow-up","serviceability-review","nurture","pause"]}},{"name":"needs","in":"query","schema":{"type":"string","enum":["kevin","tom","product","compliance"]}},{"name":"top_prospect","in":"query","schema":{"type":"boolean"},"description":"Filters the curator-owned Top prospects shortlist flag."},{"name":"funnel_stage","in":"query","schema":{"type":"string","enum":["initial-contact","in-discovery","opportunity-identified","qualified-prospect"]},"description":"Filters on the effective funnel stage: funnel_stage_override when set, else derived from stage/classification/handoff/opportunity fields using the same mapping as the GTM page."},{"name":"relationship_freshness","in":"query","schema":{"type":"string","enum":["live","quiet"]},"description":"Filters the 7-day relationship clock. quiet returns dated evidence older than 7 days or a curator Quiet hold (never missing/unparseable dates without a hold). live returns a dated event in the last 7 days or an unexpired mark_live_until, unless a Quiet hold is active."}],"responses":{"200":{"description":"GTM assignments with the six-field overview projection.","content":{"application/json":{"schema":{"type":"object","properties":{"assignments":{"type":"array","items":{"type":"object","properties":{"overview":{"$ref":"#/components/schemas/GtmAssignmentOverview"},"relationship_freshness":{"type":"string","enum":["live","quiet"],"description":"7-day relationship clock. live = dated event in the last 7 days or an unexpired mark_live_until. An active quiet_held_at hold is Quiet even with a recent last_touch. Missing or unparseable dates set last_event_at to null and must not be treated as a Quiet flag unless quiet_held_at is set."},"last_event_at":{"type":"string","format":"date-time","nullable":true,"description":"ISO timestamp of the latest dated last_touch or linked person touchpoint. Null when no dated event is known."},"mark_live_until":{"type":"string","format":"date-time","nullable":true},"quiet_held_at":{"type":"string","format":"date-time","nullable":true,"description":"Curator Quiet hold. Null when not held. Cleared by Mark live or a later dated last_touch/touchpoint write."},"call_job":{"type":"string","nullable":true},"next_validation":{"type":"string","nullable":true}}}}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"}}},"post":{"summary":"Create or update a GTM entity assignment","description":"Upserts by (segment, entity). Use this for agent-assisted GTM board management after curator approval or with an explicitly trusted GTM key. HONESTY GUARD: setting `stage` (moving into the In-motion surface) REQUIRES `source_ref` evidence. Normal call/intel agents should usually submit `gtm_upsert_assignment` through /agents/proposals/bundle instead.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"entity_slug":{"type":"string","example":"strategy"},"entity_id":{"type":"string","format":"uuid"},"segment_slug":{"type":"string","example":"treasuries"},"segment_id":{"type":"string","format":"uuid"},"lane":{"type":"string","enum":["primary","secondary","watching"]},"status":{"type":"string","enum":["active","parked","removed"]},"fit":{"type":"string"},"rationale":{"type":"string"},"next_action":{"type":"string"},"owner":{"type":"string","description":"Account Owner — the teammate accountable for moving this GTM assignment."},"sort_order":{"type":"integer"},"stage":{"type":"string","nullable":true,"enum":["spoken-to","booked","introduced","follow-up","handoff"],"description":"GTM stage when in motion. null/omitted = research pool only (not shown as momentum)."},"handoff_state":{"type":"string","nullable":true,"enum":["ecosystem","needs-right-person","bd-handoff","product-follow-up","serviceability-review","nurture","pause"]},"classification":{"type":"string","nullable":true,"enum":["bd-ready","product-discovery","watchlist","not-relevant"]},"outreach_status":{"type":"string","enum":["not-contacted","reach-out-next","reached-out","replied"],"description":"Pre-motion reach-out funnel for the research pool."},"learned":{"type":"string","nullable":true,"description":"What the conversation revealed (markdown ok)."},"needs":{"type":"array","items":{"type":"string","enum":["kevin","tom","product","compliance"]},"nullable":true},"pillars":{"type":"object","nullable":true,"additionalProperties":{"type":"string","enum":["confirmed","hypothesized","not-relevant","asked-unanswered","unknown"]},"description":"Per-pillar signal for the GTM page, e.g. trading/payment/treasury/yield/access-to-capital-markets mapped to confirmed, hypothesized, not-relevant, asked-unanswered, or unknown."},"product_signal":{"type":"object","nullable":true,"properties":{"area":{"type":"string"},"insight":{"type":"string"}},"description":"Concrete product/service implication from the source."},"service_lane":{"type":"string","nullable":true,"description":"Core service area: trading|payments|treasury|custody|liquidity|swap-engine|onboarding."},"contact_path":{"type":"string","nullable":true},"active_channel":{"type":"string","nullable":true},"right_next_person":{"type":"string","nullable":true},"blocker":{"type":"string","nullable":true},"contact_origin":{"type":"string","nullable":true,"description":"How the relationship was established: linkedin|conference|event|warm-intro|referral|personal|inbound|cold-outreach|other."},"contact_origin_detail":{"type":"string","nullable":true,"description":"Free text, e.g. 'BTC Prague 2026' or 'intro via Christian'."},"comms_channel":{"type":"string","nullable":true,"description":"Where comms happen: email|signal|telegram|whatsapp|phone|linkedin|in-person|other."},"client_for":{"type":"string","nullable":true,"description":"Potential client opportunity — what we could sell them (e.g. Custody API)."},"partner_for":{"type":"string","nullable":true,"description":"Potential partner opportunity — what we could partner on (e.g. Hashrate banking services)."},"commercial_weight":{"type":"string","nullable":true,"enum":["shrimp","fish","shark","whale"],"description":"Commercial Size shown on the GTM overview."},"top_prospect":{"type":"boolean","description":"Pins the account to the manually curated Top prospects shortlist without changing funnel stage or routing."},"source_ref":{"type":"object","nullable":true,"properties":{"label":{"type":"string"},"href":{"type":"string"}},"description":"Provenance pointer (capture/deal/note)."},"last_touch":{"type":"string","nullable":true},"call_job":{"type":"string","nullable":true,"description":"Concrete use for the next call. Never generic liquidity or OTC. Empty is valid."},"next_validation":{"type":"string","nullable":true,"description":"One question to answer in the next 30 minutes. Empty is valid."},"call_workflow":{"type":"string","nullable":true,"description":"Optional next-call note. Empty is valid."},"call_cost":{"type":"string","nullable":true,"description":"Optional next-call note. Empty is valid."},"call_architecture":{"type":"string","nullable":true,"description":"Optional next-call note. Empty is valid."},"call_controls":{"type":"string","nullable":true,"description":"Optional next-call note. Empty is valid."},"call_evidence":{"type":"string","nullable":true,"description":"Optional next-call note. Empty is valid."},"call_unknowns":{"type":"string","nullable":true,"description":"Optional next-call note. Empty is valid."},"mark_live_until":{"type":"string","format":"date-time","nullable":true,"description":"Curator override expiry for Live this week. Not a sticky boolean; expires unless a real dated event lands."},"quiet_held_at":{"type":"string","format":"date-time","nullable":true,"description":"Curator Quiet hold. Set to an ISO timestamp to hold Quiet, or null to clear. Do not invent on a Fathom extract."},"mark_quiet":{"type":"boolean","description":"If true, stamps quiet_held_at to now and clears mark_live_until without changing last_touch. A non-null last_touch in the same write still clears the hold."},"likelihood":{"type":"string","nullable":true,"enum":["High","Medium","Low","None"],"description":"Conversion potential (curator judgement). None = structurally impossible to convert, e.g. competitor-owned."},"funnel_stage_override":{"type":"string","nullable":true,"enum":["initial-contact","in-discovery","opportunity-identified","qualified-prospect"],"description":"Curator-pinned funnel stage. When set, this is returned as funnel_stage instead of the derived value; it does not modify stage/classification/handoff_state/client_for/partner_for. Null/omitted leaves the funnel stage derived."},"unreachable_reason":{"type":"string","nullable":true,"description":"Non-null marks the account unreachable for BD (e.g. Tether-owned); other reachability buckets derive from outreach evidence."},"sizing":{"type":"object","nullable":true,"description":"The entity's own estimated revenue (market size) plus scale: hashrate/capacity and share of its own vertical market. Revenue is from monthly Bitcoin production by vertical; method states how the number was made.","properties":{"est_monthly_revenue_btc":{"type":"number"},"est_annual_revenue_usd":{"type":"integer"},"est_monthly_volume_usd":{"type":"integer"},"method":{"type":"string"},"hashrate_eh":{"type":"number","description":"Installed/operated hashrate, EH/s."},"capacity_mw":{"type":"number","description":"Capacity in MW, for hosting/infra."},"market_share_pct":{"type":"number","description":"Share of its vertical market (0-100)."},"market_label":{"type":"string","description":"What the share is of, e.g. 'network hashrate', 'firmware market'."}}}}}}}},"responses":{"201":{"description":"Assignment created or updated, including the six-field overview projection.","content":{"application/json":{"schema":{"type":"object","properties":{"assignment":{"type":"object","properties":{"overview":{"$ref":"#/components/schemas/GtmAssignmentOverview"},"relationship_freshness":{"type":"string","enum":["live","quiet"],"description":"7-day relationship clock. live = dated event in the last 7 days or an unexpired mark_live_until. An active quiet_held_at hold is Quiet even with a recent last_touch. Missing or unparseable dates set last_event_at to null and must not be treated as a Quiet flag unless quiet_held_at is set."},"last_event_at":{"type":"string","format":"date-time","nullable":true,"description":"ISO timestamp of the latest dated last_touch or linked person touchpoint. Null when no dated event is known."},"mark_live_until":{"type":"string","format":"date-time","nullable":true},"quiet_held_at":{"type":"string","format":"date-time","nullable":true,"description":"Curator Quiet hold. Null when not held. Cleared by Mark live or a later dated last_touch/touchpoint write."},"call_job":{"type":"string","nullable":true},"next_validation":{"type":"string","nullable":true}}}}}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/gtm/assignments/{id}":{"patch":{"summary":"Patch a GTM assignment","description":"Update one trusted GTM assignment. If `stage` is set to an in-motion value, the row must already have source_ref or this patch must include source_ref.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"lane":{"type":"string","enum":["primary","secondary","watching"]},"status":{"type":"string","enum":["active","parked","removed"]},"fit":{"type":"string"},"rationale":{"type":"string"},"next_action":{"type":"string"},"owner":{"type":"string","nullable":true},"sort_order":{"type":"integer"},"stage":{"type":"string","nullable":true,"enum":["spoken-to","booked","introduced","follow-up","handoff"]},"handoff_state":{"type":"string","nullable":true,"enum":["ecosystem","needs-right-person","bd-handoff","product-follow-up","serviceability-review","nurture","pause"]},"classification":{"type":"string","nullable":true,"enum":["bd-ready","product-discovery","watchlist","not-relevant"]},"outreach_status":{"type":"string","enum":["not-contacted","reach-out-next","reached-out","replied"]},"learned":{"type":"string","nullable":true},"needs":{"type":"array","items":{"type":"string","enum":["kevin","tom","product","compliance"]},"nullable":true},"pillars":{"type":"object","nullable":true,"additionalProperties":{"type":"string","enum":["confirmed","hypothesized","not-relevant","asked-unanswered","unknown"]}},"product_signal":{"type":"object","nullable":true,"properties":{"area":{"type":"string"},"insight":{"type":"string"}}},"service_lane":{"type":"string","nullable":true},"contact_path":{"type":"string","nullable":true},"active_channel":{"type":"string","nullable":true},"right_next_person":{"type":"string","nullable":true},"blocker":{"type":"string","nullable":true},"contact_origin":{"type":"string","nullable":true},"contact_origin_detail":{"type":"string","nullable":true},"comms_channel":{"type":"string","nullable":true},"client_for":{"type":"string","nullable":true,"description":"Potential client opportunity — what we could sell them."},"partner_for":{"type":"string","nullable":true,"description":"Potential partner opportunity — what we could partner on."},"commercial_weight":{"type":"string","nullable":true,"enum":["shrimp","fish","shark","whale"],"description":"Commercial Size shown on the GTM overview."},"top_prospect":{"type":"boolean","description":"Pins the account to the manually curated Top prospects shortlist without changing funnel stage or routing."},"source_ref":{"type":"object","nullable":true,"properties":{"label":{"type":"string"},"href":{"type":"string"}}},"last_touch":{"type":"string","nullable":true},"call_job":{"type":"string","nullable":true,"description":"Concrete use for the next call. Never generic liquidity or OTC. Empty is valid."},"next_validation":{"type":"string","nullable":true,"description":"One question to answer in the next 30 minutes. Empty is valid."},"call_workflow":{"type":"string","nullable":true,"description":"Optional next-call note. Empty is valid."},"call_cost":{"type":"string","nullable":true,"description":"Optional next-call note. Empty is valid."},"call_architecture":{"type":"string","nullable":true,"description":"Optional next-call note. Empty is valid."},"call_controls":{"type":"string","nullable":true,"description":"Optional next-call note. Empty is valid."},"call_evidence":{"type":"string","nullable":true,"description":"Optional next-call note. Empty is valid."},"call_unknowns":{"type":"string","nullable":true,"description":"Optional next-call note. Empty is valid."},"mark_live_until":{"type":"string","format":"date-time","nullable":true,"description":"Curator override expiry for Live this week. Not a sticky boolean; expires unless a real dated event lands."},"quiet_held_at":{"type":"string","format":"date-time","nullable":true,"description":"Curator Quiet hold. Set to an ISO timestamp to hold Quiet, or null to clear. Do not invent on a Fathom extract."},"mark_quiet":{"type":"boolean","description":"If true, stamps quiet_held_at to now and clears mark_live_until without changing last_touch. A non-null last_touch in the same write still clears the hold."},"likelihood":{"type":"string","nullable":true,"enum":["High","Medium","Low","None"],"description":"Conversion potential (curator judgement). None = structurally impossible to convert, e.g. competitor-owned."},"funnel_stage_override":{"type":"string","nullable":true,"enum":["initial-contact","in-discovery","opportunity-identified","qualified-prospect"],"description":"Curator-pinned funnel stage. When set, this is returned as funnel_stage instead of the derived value; it does not modify stage/classification/handoff_state/client_for/partner_for. Set to null to clear the pin and fall back to the derived value."},"unreachable_reason":{"type":"string","nullable":true,"description":"Non-null marks the account unreachable for BD (e.g. Tether-owned); other reachability buckets derive from outreach evidence."},"sizing":{"type":"object","nullable":true,"description":"The entity's own estimated revenue (market size) plus scale: hashrate/capacity and share of its own vertical market. Revenue is from monthly Bitcoin production by vertical; method states how the number was made.","properties":{"est_monthly_revenue_btc":{"type":"number"},"est_annual_revenue_usd":{"type":"integer"},"est_monthly_volume_usd":{"type":"integer"},"method":{"type":"string"},"hashrate_eh":{"type":"number","description":"Installed/operated hashrate, EH/s."},"capacity_mw":{"type":"number","description":"Capacity in MW, for hosting/infra."},"market_share_pct":{"type":"number","description":"Share of its vertical market (0-100)."},"market_label":{"type":"string","description":"What the share is of, e.g. 'network hashrate', 'firmware market'."}}}}}}}},"responses":{"200":{"description":"Updated assignment, including the six-field overview projection.","content":{"application/json":{"schema":{"type":"object","properties":{"assignment":{"type":"object","properties":{"overview":{"$ref":"#/components/schemas/GtmAssignmentOverview"},"relationship_freshness":{"type":"string","enum":["live","quiet"],"description":"7-day relationship clock. live = dated event in the last 7 days or an unexpired mark_live_until. An active quiet_held_at hold is Quiet even with a recent last_touch. Missing or unparseable dates set last_event_at to null and must not be treated as a Quiet flag unless quiet_held_at is set."},"last_event_at":{"type":"string","format":"date-time","nullable":true,"description":"ISO timestamp of the latest dated last_touch or linked person touchpoint. Null when no dated event is known."},"mark_live_until":{"type":"string","format":"date-time","nullable":true},"quiet_held_at":{"type":"string","format":"date-time","nullable":true,"description":"Curator Quiet hold. Null when not held. Cleared by Mark live or a later dated last_touch/touchpoint write."},"call_job":{"type":"string","nullable":true},"next_validation":{"type":"string","nullable":true}}}}}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/gtm/briefs":{"get":{"summary":"List GTM intelligence briefs","responses":{"200":{"description":"Brief list."},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"}}},"post":{"summary":"Create or update a GTM intelligence brief","description":"Stores a weekly intelligence brief draft/review/published record. Brief links point back to Atlas entities, GTM segments, and sources.","responses":{"201":{"description":"Brief created or updated."},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"}}}},"/gtm/briefs/{id}/links":{"get":{"summary":"List links for a GTM brief","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Brief links."}}},"post":{"summary":"Attach an entity, segment, or source to a GTM brief","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"201":{"description":"Brief link created."},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/field-events":{"get":{"summary":"List Field Intel events","description":"Lists conference, summit, meetup, roadshow, and webinar planning records for the Events dashboard. Requires read:gtm. Filter by status, priority, kind, segment slug/id, entity slug/id, person slug/id, or name search.","parameters":[{"name":"status","in":"query","schema":{"type":"string","enum":["researching","planning","outreach","booked","attended","follow_up","skipped"]}},{"name":"priority","in":"query","schema":{"type":"string","enum":["must_attend","high","medium","watch","skip"]}},{"name":"kind","in":"query","schema":{"type":"string","enum":["conference","summit","meetup","side_event","roadshow","webinar","other"]}},{"name":"segment","in":"query","schema":{"type":"string"}},{"name":"entity","in":"query","schema":{"type":"string"}},{"name":"person","in":"query","schema":{"type":"string"}},{"name":"q","in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"Event list.","content":{"application/json":{"schema":{"type":"object","properties":{"events":{"type":"array","items":{"$ref":"#/components/schemas/FieldEvent"}}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}},"post":{"summary":"Create or update a Field Intel event","description":"Trusted direct write for the Events operating surface. Upserts by slug when provided, otherwise generates a slug from the name. Requires write:gtm; normal entity/dossier enrichment should still go through curator-reviewed proposals.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FieldEventInput"}}}},"responses":{"201":{"description":"Event created or updated.","content":{"application/json":{"schema":{"type":"object","properties":{"event":{"$ref":"#/components/schemas/FieldEvent"}}}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"}}}},"/field-events/{slug}":{"get":{"summary":"Read one Field Intel event","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Event detail.","content":{"application/json":{"schema":{"type":"object","properties":{"event":{"$ref":"#/components/schemas/FieldEvent"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}},"patch":{"summary":"Patch one Field Intel event","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FieldEventInput"}}}},"responses":{"200":{"description":"Event updated."},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/field-events/{slug}/entities":{"post":{"summary":"Attach an entity to a Field Intel event","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FieldEventEntityLinkInput"}}}},"responses":{"201":{"description":"Entity link created or updated."},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/field-events/{slug}/people":{"post":{"summary":"Attach a person to a Field Intel event","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FieldEventPersonLinkInput"}}}},"responses":{"201":{"description":"Person link created or updated."},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/field-events/{slug}/segments":{"post":{"summary":"Attach a segment to a Field Intel event","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FieldEventSegmentLinkInput"}}}},"responses":{"201":{"description":"Segment link created or updated."},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/field-events/{slug}/goals":{"post":{"summary":"Add a goal to a Field Intel event","description":"Adds a structured, trackable goal (e.g. \"Book 3 treasury custody meetings\") scored into the post-event scorecard. Requires write:gtm.","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FieldEventGoalInput"}}}},"responses":{"201":{"description":"Goal created.","content":{"application/json":{"schema":{"type":"object","properties":{"event":{"$ref":"#/components/schemas/FieldEvent"}}}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/field-events/{slug}/goals/{goalId}":{"patch":{"summary":"Update a Field Intel event goal","description":"Typically used to move status and progress_value. Requires write:gtm.","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string"}},{"name":"goalId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FieldEventGoalPatchInput"}}}},"responses":{"200":{"description":"Goal updated.","content":{"application/json":{"schema":{"type":"object","properties":{"event":{"$ref":"#/components/schemas/FieldEvent"}}}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/field-events/{slug}/interactions":{"post":{"summary":"Log a meeting/touchpoint at a Field Intel event","description":"Resolves to an entity_id/entity_slug, a person_id/person_slug, or a freeform counterpart_name for a contact not in Atlas yet. Requires write:gtm.","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FieldEventInteractionInput"}}}},"responses":{"201":{"description":"Interaction created.","content":{"application/json":{"schema":{"type":"object","properties":{"event":{"$ref":"#/components/schemas/FieldEvent"}}}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/field-events/{slug}/interactions/{interactionId}":{"patch":{"summary":"Update a Field Intel event interaction","description":"Update a meeting's status, outcome notes, signal strength, or next step. Requires write:gtm.","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string"}},{"name":"interactionId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FieldEventInteractionPatchInput"}}}},"responses":{"200":{"description":"Interaction updated.","content":{"application/json":{"schema":{"type":"object","properties":{"event":{"$ref":"#/components/schemas/FieldEvent"}}}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/field-events/{slug}/follow-ups":{"post":{"summary":"Add a follow-up action item to a Field Intel event","description":"Optionally linked to an interaction, entity, or person. Requires write:gtm.","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FieldEventFollowUpInput"}}}},"responses":{"201":{"description":"Follow-up created.","content":{"application/json":{"schema":{"type":"object","properties":{"event":{"$ref":"#/components/schemas/FieldEvent"}}}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/field-events/{slug}/follow-ups/{followUpId}":{"patch":{"summary":"Update a Field Intel event follow-up","description":"Update a follow-up's status (open/in_progress/done/cancelled) or fields. Setting status to done without an explicit completed_at stamps it with the current time. Requires write:gtm.","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string"}},{"name":"followUpId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FieldEventFollowUpPatchInput"}}}},"responses":{"200":{"description":"Follow-up updated.","content":{"application/json":{"schema":{"type":"object","properties":{"event":{"$ref":"#/components/schemas/FieldEvent"}}}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/field-events/{slug}/captures":{"post":{"summary":"Hallway dump: log a floor conversation into Field Intel","description":"One write creates a completed interaction, upserts person (and org) roster candidates, and optionally opens a follow-up. Unknown names are allowed. Never creates a canonical person or entity. Requires write:gtm.","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FloorCaptureInput"}}}},"responses":{"201":{"description":"Floor capture written to FieldEvent tables.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FloorCaptureResult"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/field-events/{slug}/scorecard":{"get":{"summary":"Read a Field Intel event's post-event scorecard","description":"Returns the curator-entered qualitative verdict and 30/90-day review notes, or null if no scorecard row exists yet. Requires read:gtm.","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Scorecard, or null.","content":{"application/json":{"schema":{"type":"object","properties":{"scorecard":{"anyOf":[{"$ref":"#/components/schemas/FieldEventScorecard"},{"type":"null"}]}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}},"patch":{"summary":"Upsert a Field Intel event's post-event scorecard","description":"One row per event (upserted by field_event_id) — there is no separate create endpoint. Carries verdict, review notes, team time, and reported cost; quantitative metrics are derived elsewhere, never stored here. Requires write:gtm.","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FieldEventScorecardPatchInput"}}}},"responses":{"200":{"description":"Scorecard upserted.","content":{"application/json":{"schema":{"type":"object","properties":{"event":{"$ref":"#/components/schemas/FieldEvent"}}}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/field-events/{slug}/roster":{"get":{"summary":"Read a Field Intel event's roster candidates","description":"Lists agent-discovered roster candidates (sponsors, exhibitors, speakers, organizers, media, attendees, other targets) staged for this event, filterable by role, review_status, and meeting_target. Requires read:gtm.","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string"}},{"name":"role","in":"query","schema":{"type":"string","enum":["sponsor","exhibitor","speaker","organizer","host","media","attendee","partner","target","competitor","other"]}},{"name":"review_status","in":"query","schema":{"type":"string","enum":["unreviewed","matched","promoted","dismissed"]}},{"name":"meeting_target","in":"query","schema":{"type":"boolean"}}],"responses":{"200":{"description":"Roster candidate list.","content":{"application/json":{"schema":{"type":"object","properties":{"roster":{"type":"array","items":{"$ref":"#/components/schemas/FieldEventRosterCandidate"}}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}},"post":{"summary":"Bulk-ingest roster candidates discovered by an agent","description":"Agent-first conference ingestion: the calling agent researches the event externally (its own website, sponsor/speaker pages) and posts up to 200 structured candidates per call with source evidence. This endpoint does NOT scrape or fetch URLs itself — source_url/evidence_note are the agent's citations. Idempotent: re-posting the same candidates (matched by external_ref, or by role + a normalized display_name) updates the existing rows instead of duplicating them. Every candidate lands as an event-scoped staging row; it never creates a canonical entity/person — promote via /v1/agents/proposals/entity or /v1/agents/proposals/person once a curator or agent workflow confirms it. But a candidate that explicitly carries matched_entity_id/slug or matched_person_id/slug is treated as an assertion that the record already exists: this also idempotently upserts the matching field_event_entities/field_event_people row (role mapped onto the narrower canonical vocabulary, plus meeting_target/outreach_status/next_step/relationship_note), keyed on (field_event_id, entity_id or person_id, role). An unmatched candidate stays staged only, and clearing a match later never deletes a canonical link already created. Requires write:gtm.","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FieldEventRosterBulkInput"}}}},"responses":{"201":{"description":"Candidates created and/or updated.","content":{"application/json":{"schema":{"type":"object","properties":{"created":{"type":"integer"},"updated":{"type":"integer"},"roster":{"type":"array","items":{"$ref":"#/components/schemas/FieldEventRosterCandidate"}}}}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/field-events/{slug}/roster/{candidateId}":{"patch":{"summary":"Refine one Field Intel event roster candidate","description":"Correct fields, resolve to an existing entity/person (matched_entity_id/slug or matched_person_id/slug — setting one clears the other), mark it a meeting target, move outreach status, or set review_status (dismissed/promoted). Setting a match without an explicit review_status auto-advances it to \"matched\". Never creates a *new* canonical entity/person. But linking to an *existing* one idempotently upserts the matching field_event_entities/field_event_people row too (role mapped onto the narrower canonical vocabulary, plus meeting_target/outreach_status/next_step/relationship_note), so the match is a real bidirectional canonical link, not just a pointer on the staging row. Clearing a match (dismissing/unmatching) never deletes a canonical link that already exists. Requires write:gtm.","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string"}},{"name":"candidateId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FieldEventRosterPatchInput"}}}},"responses":{"200":{"description":"Candidate updated.","content":{"application/json":{"schema":{"type":"object","properties":{"candidate":{"$ref":"#/components/schemas/FieldEventRosterCandidate"}}}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/discovery-sprints/{sprint}/targets/{target}":{"get":{"summary":"Read one discovery sprint target","description":"Returns bot-writable operating intelligence for one discovery sprint target: status, pain points, opportunities, current providers, contacts, key metrics, relationship label, next action, meeting summaries/Fathom links, source links, and missing info.","parameters":[{"name":"sprint","in":"path","required":true,"schema":{"type":"string"}},{"name":"target","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Discovery target payload."},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}},"post":{"summary":"Update one discovery sprint target","description":"Updates structured sprint operating fields after a bot log command or meeting. This is a direct write, not an inbox proposal, and requires the separately granted write:discovery-sprints scope. Proposal-only credentials cannot call it.","parameters":[{"name":"sprint","in":"path","required":true,"schema":{"type":"string"}},{"name":"target","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","enum":["identified","warm_path_needed","outreach_ready","contacted","scheduled","briefed","interviewed","follow_up","synthesized","parked"]},"pain_points":{"type":"array","items":{"type":"string"}},"opportunities":{"type":"array","items":{"type":"string"}},"current_providers":{"type":"array","items":{"type":"object","additionalProperties":true}},"contacts":{"type":"array","items":{"type":"object","additionalProperties":true}},"key_metrics":{"type":"object","additionalProperties":true},"relationship_label":{"type":"string","enum":["client","partner","competitor","supplier","watch","unknown"],"nullable":true},"next_action":{"type":"string","nullable":true},"meeting_summaries":{"type":"array","items":{"type":"object","additionalProperties":true}},"source_links":{"type":"array","items":{"type":"object","additionalProperties":true}},"build_vs_buy_signal":{"type":"string","nullable":true},"willingness_to_pay_signal":{"type":"string","nullable":true},"missing_info":{"type":"array","items":{"type":"string"}}},"additionalProperties":false}}}},"responses":{"200":{"description":"Updated discovery target payload."},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/segments/{slug}":{"get":{"summary":"Get one segment with optional Dossier embed","description":"Returns a single segment by slug, optionally with the segment-level Dossier. The Dossier is a curator-authored markdown narrative explaining how the segment actually works: structural dynamics, key flows, chokepoints, dominant business models. Use `?include=lore` (default) to include the narrative body; pass `?include=` (empty) for just the segment metadata.","parameters":[{"name":"slug","in":"path","required":true,"description":"Segment slug. e.g. 'miners', 'custody', 'lightning'.","schema":{"type":"string"}},{"name":"include","in":"query","description":"Comma-separated embeds. Currently supported: `lore`. Default is `lore`.","schema":{"type":"string"}}],"responses":{"200":{"description":"Segment with optional dossier embed.","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Segment"},{"type":"object","properties":{"lore":{"type":"object","description":"Segment dossier. Empty body when no dossier has been written.","properties":{"body":{"type":"string"},"current_version_id":{"type":"string","format":"uuid","nullable":true},"last_edited_at":{"type":"string","format":"date-time","nullable":true}}}}}]}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/atlas/segments/{slug}/drilldown":{"get":{"summary":"Get a page-shaped Atlas segment drill-down","description":"Agent-friendly read model for Atlas drill-down pages. Uses entity_segments membership, includes child segments by default, and returns segment_resolution for each entity so agents can see primary top-level segment, subsegment breadcrumb, all memberships, taxonomy terms, and display paths.","parameters":[{"name":"slug","in":"path","required":true,"description":"Segment slug, e.g. treasuries, custody, governments.","schema":{"type":"string"}},{"name":"limit","in":"query","description":"Maximum entities to return. Default 200, max 500.","schema":{"type":"integer","minimum":1,"maximum":500,"default":200}},{"name":"include_children","in":"query","description":"When true/default, parent drilldowns include entities from child segment memberships. Use false for exact segment membership only.","schema":{"type":"string","enum":["true","false"],"default":"true"}}],"responses":{"200":{"description":"Drill-down read model.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DrilldownResponse"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/atlas/segments/{slug}/drilldown/proposals":{"post":{"summary":"Propose drill-down curation updates","description":"Segment-scoped write surface for agents working from a drill-down page. Creates curator-reviewed inbox proposals; it never directly mutates canonical Atlas rows. Use for filling curation gaps, updating dossier summary fields, patching scale metadata, appending notes, or setting relationship status.","parameters":[{"name":"slug","in":"path","required":true,"description":"Segment slug for the drill-down context.","schema":{"type":"string"}},{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DrilldownProposalRequest"}}}},"responses":{"200":{"$ref":"#/components/responses/ProposalReplayed"},"201":{"$ref":"#/components/responses/ProposalCreated"},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/atlas/visualization/overlaps":{"get":{"summary":"Get heuristic Atlas role-overlap buckets","description":"Returns read-only Venn/overlap data for exactly three Atlas visualization roles. This is a heuristic wiki lens for discovery and mapping, not a canonical GTM assignment surface. Agents should use it to find bridge entities, then read entity dossiers before proposing any changes.","parameters":[{"name":"roles","in":"query","required":false,"description":"Exactly three comma-separated role slugs. Defaults to custody,liquidity,payments. Common roles include custody, liquidity, payments, mining, treasuries, lightning, compliance, banking, api-infra.","schema":{"type":"string","example":"custody,liquidity,payments"}}],"responses":{"200":{"description":"Heuristic role-overlap buckets and capped entity previews.","content":{"application/json":{"schema":{"type":"object","properties":{"heuristic":{"type":"boolean","const":true},"roles":{"type":"array","items":{"type":"object","properties":{"slug":{"type":"string"},"label":{"type":"string"},"description":{"type":"string"},"color":{"type":"string"}}}},"buckets":{"type":"object","additionalProperties":{"type":"object","properties":{"count":{"type":"integer"},"entities":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"slug":{"type":"string"},"name":{"type":"string"},"ticker":{"type":"string","nullable":true},"segment":{"$ref":"#/components/schemas/Segment"},"strategic_importance":{"type":"integer","nullable":true},"relationship_status":{"type":"string","nullable":true},"roles":{"type":"array","items":{"type":"object","properties":{"slug":{"type":"string"},"label":{"type":"string"},"reason":{"type":"string"},"reason_label":{"type":"string"}}}}}}}}}}}}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"}}}},"/atlas/visualization/coverage":{"get":{"summary":"Get Atlas data coverage and curation gaps","description":"Returns management coverage for entity country, city, Key People, relationship path context, and source records. Use this before large cleanup runs so agents work from explicit gaps instead of guessing.","parameters":[{"name":"segment","in":"query","description":"Limit coverage to entities in this segment. Parent segments include child memberships by default.","schema":{"type":"string","example":"miners"}},{"name":"tag","in":"query","description":"Limit coverage to entities assigned this taxonomy term slug. Comma-separated slugs use OR semantics.","schema":{"type":"string","example":"lightning.wallets"}},{"name":"include_children","in":"query","description":"When segment is a parent, include child segment memberships by default. Set false for exact membership only.","schema":{"type":"string","enum":["true","false"],"default":"true"}},{"name":"sample_limit","in":"query","description":"Maximum sample entities per gap bucket and returned work items.","schema":{"type":"integer","minimum":1,"maximum":100,"default":20}}],"responses":{"200":{"description":"Coverage checks, sample gaps, and prioritized work items.","content":{"application/json":{"schema":{"type":"object","properties":{"coverage":{"$ref":"#/components/schemas/ManagementCoverage"}}}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"}}}},"/agent-work/queues":{"get":{"summary":"List Atlas agent work queues","description":"Returns stable queue definitions for data-quality cleanup work, including location, Key People, relationship path, and source gaps.","responses":{"200":{"description":"Available agent work queues.","content":{"application/json":{"schema":{"type":"object","properties":{"queues":{"type":"array","items":{"$ref":"#/components/schemas/AgentWorkQueue"}}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"}}}},"/agent-work/items":{"get":{"summary":"List prioritized Atlas cleanup work items","description":"Returns explicit data-quality work items for agents, filtered by segment, taxonomy tag, and gap kind. Each item includes the entity, reason, suggested endpoint, and expected proposal shape.","parameters":[{"name":"segment","in":"query","description":"Limit work items to entities in this segment. Parent segments include child memberships by default.","schema":{"type":"string","example":"treasuries"}},{"name":"tag","in":"query","description":"Limit work items to entities assigned this taxonomy term slug. Comma-separated slugs use OR semantics.","schema":{"type":"string","example":"lightning.infrastructure.lsp"}},{"name":"include_children","in":"query","description":"When segment is a parent, include child segment memberships by default. Set false for exact membership only.","schema":{"type":"string","enum":["true","false"],"default":"true"}},{"name":"kind","in":"query","description":"Comma-separated work kinds: missing_country, missing_city, missing_key_people, missing_relationship_path, missing_sources.","schema":{"type":"string","example":"missing_key_people,missing_relationship_path"}},{"name":"limit","in":"query","description":"Maximum returned work items.","schema":{"type":"integer","minimum":1,"maximum":200,"default":50}}],"responses":{"200":{"description":"Prioritized cleanup work items.","content":{"application/json":{"schema":{"type":"object","properties":{"generated_at":{"type":"string","format":"date-time"},"filters":{"type":"object","properties":{"segment":{"type":"string","nullable":true},"tag":{"type":"string","nullable":true},"include_children":{"type":"boolean"}}},"queues":{"type":"array","items":{"$ref":"#/components/schemas/AgentWorkQueue"}},"items":{"type":"array","items":{"$ref":"#/components/schemas/AgentWorkItem"}}}}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"}}}},"/segments":{"get":{"summary":"List ecosystem segments","description":"Returns every segment in the taxonomy ordered by sort_order. Call this before proposing entities so segment_slug values are valid. For a single segment with its Dossier body, use GET /v1/segments/{slug}.","responses":{"200":{"description":"List of segments.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Segment"}}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"}}}},"/taxonomy":{"get":{"summary":"List agent-facing taxonomy terms","description":"Returns stable taxonomy/tag slugs for agents. Use these slugs in entity filters and taxonomy assignment proposals.","parameters":[{"name":"kind","in":"query","description":"Filter by taxonomy kind.","schema":{"type":"string"}},{"name":"parent","in":"query","description":"Parent taxonomy slug.","schema":{"type":"string"}},{"name":"include_deprecated","in":"query","description":"Include deprecated terms when true.","schema":{"type":"boolean"}}],"responses":{"200":{"description":"List of taxonomy terms.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/TaxonomyTerm"}}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"}}}},"/taxonomy/{slug}":{"get":{"summary":"Get one taxonomy term","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Taxonomy term with children.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TaxonomyTerm"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/taxonomy/{slug}/entities":{"get":{"summary":"List entities assigned to a taxonomy term","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string"}},{"$ref":"#/components/parameters/LimitParam"},{"$ref":"#/components/parameters/CursorParam"}],"responses":{"200":{"description":"Paginated entities for a taxonomy term."},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/capabilities":{"get":{"summary":"List Lunar Rails capabilities","description":"Returns every capability. The slug is the load-bearing field; use it for `capability_slug` in lr_fit and provider proposals.","responses":{"200":{"description":"List of capabilities.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Capability"}}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"}}}},"/needs":{"get":{"summary":"List demand-side needs","description":"Returns every need in the taxonomy. Needs map to capabilities via primary_capability_id.","responses":{"200":{"description":"List of needs.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Need"}}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"}}}},"/verticals":{"get":{"summary":"List sub-classification verticals","description":"Returns every vertical. Used today for mining sub-segments (self_mining, mining_pool, hosting, etc.).","responses":{"200":{"description":"List of verticals.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Vertical"}}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"}}}},"/entities":{"get":{"summary":"List catalog entities with filters","description":"The load-bearing read endpoint. Agents drive their own work queues from the filter parameters. Filters compose; pagination is cursor-based. Use `last_verified_before` for freshness work, `missing_capability` for enrichment work, `needs_research=true` for entities with thin metadata.","parameters":[{"name":"segment","in":"query","description":"Entities with this segment membership. Parent segments include child memberships by default.","schema":{"type":"string","example":"custody"}},{"name":"include_children","in":"query","description":"When segment is a parent, include child segment memberships by default. Set false for exact membership only.","schema":{"type":"string","enum":["true","false"],"default":"true"}},{"name":"posture","in":"query","description":"Bitcoin posture enum.","schema":{"type":"string","enum":["producer","holder","allocator","service_provider","merchant","institution","infrastructure"]}},{"name":"competitive_posture","in":"query","description":"Lunar overlay posture enum.","schema":{"type":"string","enum":["incumbent","competitor","partner","complement","whitespace","not_applicable"]}},{"name":"country","in":"query","description":"Case-insensitive exact filter on entity country.","schema":{"type":"string","example":"United States"}},{"name":"region","in":"query","description":"Case-insensitive exact filter on entity region/state.","schema":{"type":"string","example":"Texas"}},{"name":"city","in":"query","description":"Case-insensitive exact filter on entity city.","schema":{"type":"string","example":"Austin"}},{"name":"has_lr_fit","in":"query","description":"Entities with at least one entity_lr_fit row.","schema":{"type":"string","enum":["true","false"]}},{"name":"has_providers","in":"query","description":"Entities with at least one entity_providers row.","schema":{"type":"string","enum":["true","false"]}},{"name":"missing_capability","in":"query","description":"Entities without an lr_fit row for this capability slug. Useful for enrichment runs ('find entities not yet rated for custody').","schema":{"type":"string","example":"custody"}},{"name":"tag","in":"query","description":"Entities assigned this taxonomy term slug.","schema":{"type":"string","example":"lightning.wallets.custodial"}},{"name":"any_tag","in":"query","description":"Comma-separated taxonomy slugs with OR semantics.","schema":{"type":"string","example":"lightning.wallets,lightning.infrastructure.lsp"}},{"name":"all_tags","in":"query","description":"Comma-separated taxonomy slugs with AND semantics.","schema":{"type":"string","example":"lightning,lightning.wallets,lightning.wallets.custodial"}},{"name":"last_verified_before","in":"query","description":"ISO date-time. Returns entities whose last_verified_at is older than this. Drives the verification agent loop.","schema":{"type":"string","format":"date-time"}},{"name":"needs_research","in":"query","description":"Convenience predicate: entities with neither lr_fit nor providers.","schema":{"type":"string","enum":["true"]}},{"name":"name","in":"query","description":"Case-insensitive substring search on the name field.","schema":{"type":"string"}},{"$ref":"#/components/parameters/LimitParam"},{"$ref":"#/components/parameters/CursorParam"}],"responses":{"200":{"description":"Paginated list of entities matching the filters.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EntityListResponse"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"}}}},"/agents/proposals":{"get":{"summary":"List your proposals","description":"Return proposals visible to the calling agent. Defaults to mine_only=true so each agent sees its own backlog. Closes the feedback loop: an agent can check what it proposed earlier and which proposals the curator accepted, rejected, or left pending — without trawling the inbox UI.","parameters":[{"name":"status","in":"query","description":"Comma-separated subset of: pending, accepted, rejected, unmatched. Default returns all.","schema":{"type":"string"}},{"name":"target_entity","in":"query","description":"Filter to one entity's proposals (slug or UUID).","schema":{"type":"string"}},{"name":"mine_only","in":"query","description":"true (default) returns only proposals the calling agent created. Pass false for cross-agent visibility (orchestrator use).","schema":{"type":"boolean"}},{"name":"limit","in":"query","description":"Max items to return. 1..100. Default 25.","schema":{"type":"integer"}},{"name":"cursor","in":"query","description":"Pass next_cursor from the previous response to page backward through time.","schema":{"type":"string"}}],"responses":{"200":{"description":"List of proposal summaries.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/ProposalSummary"}},"next_cursor":{"type":"string","nullable":true}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"}}}},"/agents/proposals/{id}":{"get":{"summary":"Get one of your proposals with full change payload","description":"Detail view including the full proposed_changes array, applied_indices, and decision_notes from the curator review. Returns 403 when the proposal belongs to a different agent.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Proposal detail.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProposalDetail"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"description":"Proposal belongs to another agent.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"$ref":"#/components/responses/NotFound"}}}},"/agents/proposals/entity":{"post":{"summary":"Propose a new entity (optionally with enrichment)","description":"The killer-feature endpoint for conversational entity authoring. Creates a single proposal in the inbox with create_entity FIRST followed by optional enrichment changes (lr_fit, providers, events). On accept the apply pipeline creates the entity, captures the new id, then applies the enrichment against it.","parameters":[{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EntityProposalRequest"}}}},"responses":{"200":{"$ref":"#/components/responses/ProposalReplayed"},"201":{"$ref":"#/components/responses/ProposalCreated"},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"409":{"description":"An entity with this slug already exists. Use the bundle endpoint against the existing slug instead.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/agents/proposals/segments":{"post":{"summary":"Propose a new ecosystem segment","description":"Lands a create_segment change in the curator inbox. Agents never create canonical segments directly; curator acceptance inserts the segment row. Use this when the ecosystem map outgrows the current segment taxonomy.","parameters":[{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["segment"],"properties":{"segment":{"type":"object","required":["slug","name"],"properties":{"slug":{"type":"string","pattern":"^[a-z0-9-]+$","example":"self-custody-wallets"},"name":{"type":"string","example":"Self-Custody Wallets"},"description":{"type":"string","nullable":true},"parent_slug_or_id":{"type":"string","nullable":true},"hue_token":{"type":"string","nullable":true,"example":"seg-self-custody-wallets"},"sort_order":{"type":"integer"}}},"rationale":{"type":"string"},"confidence":{"type":"integer","minimum":1,"maximum":5}}}}}},"responses":{"200":{"$ref":"#/components/responses/ProposalReplayed"},"201":{"$ref":"#/components/responses/ProposalCreated"},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"409":{"description":"A segment with this slug already exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/agents/proposals/lr-fit":{"post":{"summary":"Propose lr_fit rows for an entity (batch)","description":"Lands as one pending proposal in the inbox. Each suggestion is a single lr_fit row (capability + horizon + fit_score). Curator accepts via the inbox; nothing auto-applies.","parameters":[{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LrFitProposalRequest"}}}},"responses":{"200":{"$ref":"#/components/responses/ProposalReplayed"},"201":{"$ref":"#/components/responses/ProposalCreated"},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/agents/proposals/entity-relationship":{"post":{"summary":"Publish an entity's relationship path (how contact formed + where comms live)","description":"Records how the relationship was established (origin), where the conversation happens now (channel + label), owner, last touch, and an optional timeline touchpoint. Lands as one pending update_entity_relationship_context proposal in the inbox; the curator accepts to apply it to the canonical entity fields and (if a touchpoint is included) the relationship timeline. Read it back via GET /v1/entities/{id}. Scope: write:proposals.","parameters":[{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"target_entity_id":{"type":"string","format":"uuid"},"target_entity_slug":{"type":"string","example":"braiins"},"match_rationale":{"type":"string"},"contact_origin":{"type":"string","enum":["conference","event","warm-intro","personal","linkedin","inbound","cold-outreach","partner-referral","other"],"description":"How the relationship was established (origin touch point)."},"contact_origin_detail":{"type":"string","example":"BTC Prague 2026, met at the Lunar booth"},"first_contact_at":{"type":"string","format":"date"},"current_comms_channel":{"type":"string","enum":["telegram","signal","whatsapp","email","phone","linkedin","in-person","other"],"description":"Where the conversation happens now."},"current_comms_label":{"type":"string","example":"Telegram group “Lunar × Braiins”"},"relationship_owner":{"type":"string"},"relationship_source_ref":{"type":"object","properties":{"label":{"type":"string"},"href":{"type":"string"}}},"relationship_last_touch":{"type":"string"},"touchpoint_kind":{"type":"string","enum":["conference","event","warm-intro","personal","linkedin","inbound","cold-outreach","partner-referral","channel-move","call-booked","call-complete","right-person-identified","other"],"description":"Optional — records a timeline touchpoint on the entity's relationship path."},"touchpoint_detail":{"type":"string"},"rationale":{"type":"string"},"confidence":{"type":"integer","minimum":1,"maximum":5}}}}}},"responses":{"200":{"$ref":"#/components/responses/ProposalReplayed"},"201":{"$ref":"#/components/responses/ProposalCreated"},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/agents/proposals/providers":{"post":{"summary":"Propose provider relationships for an entity (batch)","description":"Each suggestion names a capability and either a catalogued provider (provider_entity_id) or a free-text provider_name. Both can be supplied; the apply step prefers the linked entity.","parameters":[{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProvidersProposalRequest"}}}},"responses":{"200":{"$ref":"#/components/responses/ProposalReplayed"},"201":{"$ref":"#/components/responses/ProposalCreated"},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/agents/proposals/relationships":{"post":{"summary":"Propose entity-to-entity relationships (batch)","description":"Every related_entity_id must already exist in the catalog. Use UUID or slug.","parameters":[{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RelationshipsProposalRequest"}}}},"responses":{"200":{"$ref":"#/components/responses/ProposalReplayed"},"201":{"$ref":"#/components/responses/ProposalCreated"},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/agents/proposals/events":{"post":{"summary":"Propose events for an entity (batch)","description":"News items, deals, integration announcements, capital raises, etc. occurred_at is YYYY-MM-DD.","parameters":[{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EventsProposalRequest"}}}},"responses":{"200":{"$ref":"#/components/responses/ProposalReplayed"},"201":{"$ref":"#/components/responses/ProposalCreated"},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/agents/field-events/{slug}":{"get":{"summary":"Read canonical field-event metadata for proposal verification","description":"Proposal-safe event read for agents with read:atlas. Returns canonical event identity and metadata only; roster, interactions, follow-ups, assignments, ownership, and other GTM-operational data remain behind read:gtm.","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","pattern":"^[a-z0-9][a-z0-9-]*$"}}],"responses":{"200":{"description":"Canonical proposal-safe field-event metadata.","content":{"application/json":{"schema":{"type":"object","properties":{"event":{"type":"object","properties":{"slug":{"type":"string"},"name":{"type":"string"},"event_kind":{"type":"string"},"starts_at":{"type":"string","format":"date","nullable":true},"ends_at":{"type":"string","format":"date","nullable":true},"city":{"type":"string","nullable":true},"country":{"type":"string","nullable":true},"venue":{"type":"string","nullable":true},"website_url":{"type":"string","format":"uri","nullable":true},"priority":{"type":"string"},"lifecycle_status":{"type":"string"},"strategic_reason":{"type":"string","nullable":true},"outreach_goal":{"type":"string","nullable":true},"notes_md":{"type":"string","nullable":true},"updated_at":{"type":"string","format":"date-time"}}}}}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/agents/proposals/field-events":{"post":{"summary":"Propose a field event with segment/entity/people intel (batch)","description":"First submit the body with dry_run=true and review the environment-bound normalized changes and approval digest. Then submit the unchanged event intelligence with dry_run omitted/false, the returned X-Atlas-Approval-Digest, and an Idempotency-Key. operation is explicit: update never creates a missing slug, and create never overwrites an existing slug. For updates, omitted event fields preserve their current values; send an explicit null to clear a nullable field. Segment/entity/person links are also normalized against their current conflict rows: acceptance patches only explicitly supplied relationship fields and rejects stale link snapshots, so attachment-only omissions never reset curator-owned data. Resolved links become curator-visible changes; unresolved names stay in unmatched queues and are never auto-created. All changes require manual curator selection. Scopes: read:atlas and write:proposals; read:people is additionally required whenever people is non-empty.","parameters":[{"$ref":"#/components/parameters/RequiredBundleIdempotencyKey"},{"$ref":"#/components/parameters/BundleApprovalDigest"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FieldEventsProposalRequest"},"examples":{"default":{"value":{"operation":"create","event":{"slug":"btc-prague-2026","name":"BTC Prague 2026","event_kind":"conference","starts_at":"2026-06-11","ends_at":"2026-06-13","city":"Prague","country":"Czechia","priority":"high","lifecycle_status":"planning"},"segments":[{"segment_slug":"lightning","relevance":"Lightning-heavy speaker lineup"}],"entities":[{"entity_slug":"river-financial","role":"sponsor","outreach_status":"to_contact","meeting_target":true}],"people":[{"person_slug":"jane-doe","role":"speaker","outreach_status":"research"}],"unmatched_entities":["Some Startup We Haven't Catalogued"],"match_rationale":"Sourced from the published BTC Prague 2026 speaker/sponsor page.","sources":[{"url":"https://btcprague.com/2026","title":"BTC Prague 2026 site","trust_tier":"public"}],"dry_run":true}}}}}},"responses":{"200":{"description":"Dry-run preview or idempotent proposal replay.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/FieldEventProposalDryRunResponse"},{"$ref":"#/components/schemas/ProposalCreatedResponse"}]}}}},"201":{"$ref":"#/components/responses/ProposalCreated"},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"description":"The explicit create/update intent conflicts with canonical state, the approval digest drifted, or the idempotency key was reused with different content.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"428":{"description":"Idempotency-Key or X-Atlas-Approval-Digest is missing or invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/agents/validate/bundle":{"post":{"summary":"Dry-run validate a bundle proposal","description":"Validates and normalizes a bundle payload without creating inbox noise. Returns the canonical approval artifact and digest binding the active environment, resolved target, match rationale, normalized changes, and warnings. Submit the unchanged body with that digest; the submit route revalidates against live data and rejects drift.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BundleProposalRequest"}}}},"responses":{"200":{"description":"Valid dry-run preview.","content":{"application/json":{"schema":{"type":"object","properties":{"valid":{"type":"boolean"},"dry_run":{"type":"boolean"},"environment":{"type":"string","enum":["production","staging"]},"would_create":{"type":"string"},"change_count":{"type":"integer"},"change_kinds":{"type":"array","items":{"type":"string"}},"target_entity":{"type":"object"},"match_rationale":{"type":"string"},"normalized_changes":{"type":"array","items":{"type":"object"}},"sources_received":{"type":"integer"},"warnings":{"type":"array","items":{"type":"string"}},"approval":{"type":"object","description":"Canonical exact-payload artifact to present for approval."},"approval_digest":{"type":"string","pattern":"^sha256:[a-f0-9]{64}$"},"submit_endpoint":{"type":"string","format":"uri"},"inbox_url":{"type":"string","format":"uri"}}}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/agents/proposals/bundle":{"post":{"summary":"Propose multiple change kinds in one inbox card","description":"Creates one curator inbox card containing N change kinds for one existing target entity. First call POST /agents/validate/bundle and obtain approval for its canonical artifact. Submission requires the returned digest and an idempotency key. The server independently resolves and normalizes against live data, rejects any digest drift, and scopes concurrent retries to the environment, agent, endpoint, and approved payload. Curator application remains a separate human action. Identity-changing kinds are never bulk-auto-accepted. A discovery call should land as one GTM-native card: gtm_upsert_assignment (last_touch, call_job, next_validation) plus log_person_touchpoint.","parameters":[{"$ref":"#/components/parameters/RequiredBundleIdempotencyKey"},{"$ref":"#/components/parameters/BundleApprovalDigest"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BundleProposalRequest"}}}},"responses":{"200":{"$ref":"#/components/responses/ProposalReplayed"},"201":{"$ref":"#/components/responses/ProposalCreated"},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"description":"Approval digest no longer matches current normalization, or the idempotency key was used with a different approved payload.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"428":{"description":"Idempotency-Key or X-Atlas-Approval-Digest is missing or invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/entities/{id}":{"get":{"summary":"Get a full entity dossier","description":"Returns an entity with optional embeds. The id may be a UUID or a slug. Use `?include=` to limit embeds for smaller responses.","parameters":[{"name":"id","in":"path","required":true,"description":"Entity UUID or slug.","schema":{"type":"string"}},{"name":"include","in":"query","description":"Comma-separated embeds: lr_fit, providers, relationships, events, segments, needs, verticals, people, lore. Default is all. The `lore` embed returns the entity's Dossier — the qualitative narrative body that captures operating story, flywheels, dependencies, and inside-baseball context that doesn't fit a column.","schema":{"type":"string"}}],"responses":{"200":{"description":"Entity dossier.","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/EntitySummary"},{"type":"object","properties":{"description":{"type":"string","nullable":true},"logo_url":{"type":"string","nullable":true},"website_url":{"type":"string","nullable":true},"x_url":{"type":"string","nullable":true},"linkedin_url":{"type":"string","nullable":true},"github_url":{"type":"string","nullable":true},"nostr_url":{"type":"string","nullable":true},"crunchbase_url":{"type":"string","nullable":true},"scale":{"type":"object","nullable":true},"importance_rationale":{"type":"string","nullable":true},"notes":{"type":"string","nullable":true},"aliases":{"type":"array","items":{"type":"string"}},"lr_fit":{"type":"array","items":{"type":"object"}},"providers":{"type":"array","items":{"type":"object"}},"relationships":{"type":"array","items":{"type":"object"}},"events":{"type":"array","items":{"type":"object"}},"segments":{"type":"array","items":{"type":"object"}},"needs":{"type":"array","items":{"type":"object"}},"verticals":{"type":"array","items":{"type":"object"}},"people":{"type":"array","description":"Key people attached to this entity through person_entity_roles. Use this for account mapping: primary contacts, decision makers, warm paths, and next actions.","items":{"type":"object","properties":{"role_kind":{"type":"string"},"role_label":{"type":"string","nullable":true},"is_primary":{"type":"boolean"},"start_date":{"type":"string","format":"date","nullable":true},"end_date":{"type":"string","format":"date","nullable":true},"person":{"type":"object"}}}},"lore":{"type":"object","description":"Dossier narrative. Empty body when no dossier has been written.","properties":{"body":{"type":"string"},"current_version_id":{"type":"string","format":"uuid","nullable":true},"last_edited_at":{"type":"string","format":"date-time","nullable":true}}}}}]}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/entities/{id}/sources":{"get":{"summary":"List sources backing an entity's Dossier","description":"Returns every source row attached to the entity. Each row carries a trust_tier (public, reputable, private, rumor) so agents can decide how cite-able the source is. File-backed sources return only metadata; call GET /sources/{id} to mint a signed download URL.","parameters":[{"name":"id","in":"path","required":true,"description":"Entity UUID or slug.","schema":{"type":"string"}}],"responses":{"200":{"description":"List of sources.","content":{"application/json":{"schema":{"type":"object","properties":{"entity_id":{"type":"string","format":"uuid"},"entity_slug":{"type":"string"},"data":{"type":"array","items":{"$ref":"#/components/schemas/SourceSummary"}}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/sources/{id}":{"get":{"summary":"Get a source with a signed download URL","description":"Returns the full source row plus a short-lived signed download URL for file-backed sources. URL-only sources return the original URL directly. The signed URL expires after a few minutes; call this endpoint again to mint a fresh one.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Source detail with download URL.","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SourceSummary"},{"type":"object","properties":{"download_url":{"type":"string","nullable":true},"download_expires_in_seconds":{"type":"integer","nullable":true}}}]}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/agents/sources":{"post":{"summary":"Create a URL-based source for an entity","description":"Register a URL (press release, filing, blog post, podcast episode page) as a source backing the entity's Dossier. File uploads from agents use POST /agents/sources/upload.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["target_entity_slug_or_id","kind","title","trust_tier","url"],"properties":{"target_entity_slug_or_id":{"type":"string"},"kind":{"type":"string","enum":["transcript","deck","conversation","public_url","research","addendum"]},"title":{"type":"string"},"description":{"type":"string"},"trust_tier":{"type":"string","enum":["public","reputable","private","rumor"]},"is_referenceable":{"type":"boolean"},"external_ref":{"type":"string","description":"Stable upstream source key for idempotent registration, e.g. fathom:{meeting_id}:{entity_slug}:notes."},"url":{"type":"string","format":"uri"}}}}}},"responses":{"201":{"description":"Source created.","content":{"application/json":{"schema":{"type":"object","properties":{"source_id":{"type":"string","format":"uuid"},"entity_id":{"type":"string","format":"uuid"},"replayed":{"type":"boolean"}}}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/agents/sources/upload":{"post":{"summary":"Upload a file-backed source for an entity","description":"Upload a private or public file-backed source such as meeting notes, transcripts, raw Fathom payloads, PDFs, or Markdown research. The source becomes downloadable through GET /sources/{id}; file downloads use short-lived signed URLs.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["target_entity_slug_or_id","kind","title","trust_tier","filename","mime_type","content_base64"],"properties":{"target_entity_slug_or_id":{"type":"string"},"kind":{"type":"string","enum":["transcript","deck","conversation","public_url","research","addendum"]},"title":{"type":"string"},"description":{"type":"string"},"trust_tier":{"type":"string","enum":["public","reputable","private","rumor"]},"is_referenceable":{"type":"boolean"},"external_ref":{"type":"string","description":"Stable upstream source key. Reusing the same key returns the existing source instead of uploading a duplicate."},"filename":{"type":"string"},"mime_type":{"type":"string","enum":["text/plain","text/markdown","application/json","application/pdf"]},"content_base64":{"type":"string","description":"Base64-encoded file bytes. Max decoded size: 5 MB."}}}}}},"responses":{"200":{"description":"Existing source returned for the supplied external_ref."},"201":{"description":"Source uploaded.","content":{"application/json":{"schema":{"type":"object","properties":{"source_id":{"type":"string","format":"uuid"},"entity_id":{"type":"string","format":"uuid"},"replayed":{"type":"boolean"}}}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"}}}},"/agents/proposals/lore-update":{"post":{"summary":"Propose an update to an entity's Dossier narrative","description":"Update the qualitative Dossier body for an entity. Submit the FULL new body (not a diff). The accept step in the curator inbox replaces the canonical body and preserves the prior state in entity_lore_versions, so history is never lost. Always read the existing dossier via GET /entities/{id}?include=lore before proposing, and submit additive edits that preserve what's already there.","parameters":[{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["target_entity_slug_or_id","proposed_body","diff_summary"],"properties":{"target_entity_slug_or_id":{"type":"string","description":"Slug or UUID of the target entity."},"proposed_body":{"type":"string","maxLength":50000,"description":"Full new dossier body in markdown."},"diff_summary":{"type":"string","maxLength":200,"description":"One-line description of what changed. Shown on the inbox card."},"rationale":{"type":"string","maxLength":2000,"description":"Brief justification (sources, conversations, observations)."},"confidence":{"type":"integer","minimum":1,"maximum":5},"source_ids":{"type":"array","items":{"type":"string","format":"uuid"},"description":"Optional list of entity_lore_sources rows that back this update. They link to the new version on accept."}}}}}},"responses":{"200":{"$ref":"#/components/responses/ProposalReplayed"},"201":{"$ref":"#/components/responses/ProposalCreated"},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/people":{"get":{"summary":"List people with filters","description":"Filterable, cursor-paginated listing of people (Track P). People are the humans inside entities — founders, executives, board members, key contacts. Use the `entity` filter to find everyone affiliated with one org; `role_kind` to find all CEOs or investors; `importance_min` for the people most worth caring about. Curator-only fields (trust_blocker, next_action) are never returned here.","parameters":[{"name":"entity","in":"query","description":"People with any role at this entity (slug or UUID).","schema":{"type":"string","example":"strategy"}},{"name":"segment","in":"query","description":"People whose role-entities sit in this segment (slug).","schema":{"type":"string","example":"treasuries"}},{"name":"role_kind","in":"query","description":"Filter by person_role_kind enum.","schema":{"type":"string","enum":["founder","ceo","cfo","head_of_treasury","board","investor","advisor","employee","ex_employee","partner_contact"]}},{"name":"importance_min","in":"query","description":"Minimum importance_score (1-5).","schema":{"type":"integer","minimum":1,"maximum":5}},{"name":"posture","in":"query","description":"Case-insensitive substring on posture_toward_lr.","schema":{"type":"string"}},{"name":"name","in":"query","description":"Case-insensitive substring on the name field.","schema":{"type":"string"}},{"$ref":"#/components/parameters/LimitParam"},{"$ref":"#/components/parameters/CursorParam"}],"responses":{"200":{"description":"Paginated list of people matching the filters.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"slug":{"type":"string"},"name":{"type":"string"},"aliases":{"type":"array","items":{"type":"string"}},"country":{"type":"string","nullable":true},"city":{"type":"string","nullable":true},"avatar_url":{"type":"string","nullable":true},"website_url":{"type":"string","nullable":true},"x_url":{"type":"string","nullable":true},"linkedin_url":{"type":"string","nullable":true},"github_url":{"type":"string","nullable":true},"nostr_url":{"type":"string","nullable":true},"posture_toward_lr":{"type":"string","nullable":true},"importance_score":{"type":"integer"},"last_verified_at":{"type":"string","format":"date-time","nullable":true},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}}},"next_cursor":{"type":"string","nullable":true},"total":{"type":"integer","nullable":true}}}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"}}}},"/people/{id}":{"get":{"summary":"Get a full person dossier","description":"Returns a person with optional embeds (roles, relationships, sources). The id may be UUID or slug. Curator-only fields are filtered out — agents see the public-ish projection. Use the roles embed to find which entities this person is connected to and how.","parameters":[{"name":"id","in":"path","required":true,"description":"Person UUID or slug.","schema":{"type":"string"}},{"name":"include","in":"query","description":"Comma-separated embeds: roles, relationships, sources. Default is all.","schema":{"type":"string"}}],"responses":{"200":{"description":"Person dossier.","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"slug":{"type":"string"},"name":{"type":"string"},"aliases":{"type":"array","items":{"type":"string"}},"country":{"type":"string","nullable":true},"city":{"type":"string","nullable":true},"bio_md":{"type":"string","nullable":true},"avatar_url":{"type":"string","nullable":true},"website_url":{"type":"string","nullable":true},"x_url":{"type":"string","nullable":true},"linkedin_url":{"type":"string","nullable":true},"github_url":{"type":"string","nullable":true},"nostr_url":{"type":"string","nullable":true},"posture_toward_lr":{"type":"string","nullable":true},"importance_score":{"type":"integer"},"last_verified_at":{"type":"string","format":"date-time","nullable":true},"roles":{"type":"array","items":{"type":"object"}},"relationships":{"type":"object","properties":{"out":{"type":"array","items":{"type":"object"}},"in":{"type":"array","items":{"type":"object"}}}},"sources":{"type":"array","items":{"type":"object"}}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/people/{id}/touchpoints":{"get":{"summary":"List a person's touchpoints, newest first","description":"Person-level activity log ('had a call with X') recorded by curators or accepted from agent proposals. The id may be UUID or slug, matching /people/{id}. Use `since` to poll for new touches and `limit` to cap page size.","parameters":[{"name":"id","in":"path","required":true,"description":"Person UUID or slug.","schema":{"type":"string"}},{"name":"limit","in":"query","description":"Max rows returned. Default 50, capped at 200.","schema":{"type":"integer","minimum":1,"maximum":200,"default":50}},{"name":"since","in":"query","description":"YYYY-MM-DD; only touches on/after this occurred_at.","schema":{"type":"string","format":"date"}}],"responses":{"200":{"description":"Person identity plus their touchpoints, newest first.","content":{"application/json":{"schema":{"type":"object","properties":{"person":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"slug":{"type":"string"},"name":{"type":"string"}}},"touchpoints":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"person_id":{"type":"string","format":"uuid"},"occurred_at":{"type":"string","format":"date","nullable":true},"touchpoint_kind":{"type":"string","enum":["call","meeting","email","message","warm-intro","conference","other"]},"channel":{"type":"string","nullable":true,"enum":["telegram","signal","whatsapp","email","phone","linkedin","in-person","other"]},"label":{"type":"string","nullable":true},"detail":{"type":"string","nullable":true},"next_step":{"type":"string","nullable":true},"next_step_due_at":{"type":"string","format":"date","nullable":true},"entity":{"type":"object","nullable":true,"description":"Optional org context for the touch.","properties":{"id":{"type":"string","format":"uuid"},"slug":{"type":"string"},"name":{"type":"string"}}},"created_at":{"type":"string","format":"date-time"}}}}}}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/agents/proposals/person":{"post":{"summary":"Propose a new person or an update to an existing one","description":"Submit a person to the curator inbox (Track P). Omit `target_person_slug_or_id` to create a new person — `person.slug` and `person.name` are required. Set `target_person_slug_or_id` to update existing fields — only the keys you supply are touched on accept. Curator-only fields (trust_blocker, next_action) are silently dropped from agent input.","parameters":[{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["person"],"properties":{"target_person_slug_or_id":{"type":"string","description":"If set, this is an update_person proposal. Slug or UUID."},"person":{"type":"object","description":"Person field values. On create, `slug` + `name` are required. On update, all keys optional; missing keys stay untouched.","properties":{"slug":{"type":"string","pattern":"^[a-z0-9-]+$"},"name":{"type":"string","maxLength":200},"aliases":{"type":"array","items":{"type":"string"}},"country":{"type":"string","nullable":true},"city":{"type":"string","nullable":true},"bio_md":{"type":"string","nullable":true,"maxLength":50000},"avatar_url":{"type":"string","nullable":true},"website_url":{"type":"string","nullable":true},"x_url":{"type":"string","nullable":true},"linkedin_url":{"type":"string","nullable":true},"github_url":{"type":"string","nullable":true},"nostr_url":{"type":"string","nullable":true},"posture_toward_lr":{"type":"string","nullable":true,"maxLength":200},"importance_score":{"type":"integer","minimum":1,"maximum":5},"notes":{"type":"string","nullable":true}}},"rationale":{"type":"string","maxLength":2000},"confidence":{"type":"integer","minimum":1,"maximum":5},"raw_transcript":{"type":"string","maxLength":50000,"description":"Optional verbatim transcript or observation that backs this proposal."}}}}}},"responses":{"200":{"$ref":"#/components/responses/ProposalReplayed"},"201":{"$ref":"#/components/responses/ProposalCreated"},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"description":"A person with this slug already exists. Use target_person_slug_or_id to propose updates instead.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/agents/proposals/person-touchpoint":{"post":{"summary":"Propose a person touchpoint (activity log entry)","description":"Log a person-level touch ('had a call with X') to the curator inbox. On accept, inserts a person_touchpoints row with source_ref pointing back at the proposal and created_by set to the accepting curator. `person_slug_or_id` must resolve to an existing person — propose new people via /agents/proposals/person first. Pair with GET /people/{id}/touchpoints to read the resulting timeline. Requires the write:proposals scope.","parameters":[{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["person_slug_or_id","touchpoint_kind"],"properties":{"person_slug_or_id":{"type":"string","description":"Existing person slug or UUID."},"occurred_at":{"type":"string","format":"date","nullable":true,"description":"When the touch happened. Omit if unknown."},"touchpoint_kind":{"type":"string","enum":["call","meeting","email","message","warm-intro","conference","other"]},"channel":{"type":"string","nullable":true,"enum":["telegram","signal","whatsapp","email","phone","linkedin","in-person","other"]},"label":{"type":"string","nullable":true,"maxLength":200,"description":"One-line summary, e.g. 'Intro call re treasury pilot'."},"detail":{"type":"string","nullable":true,"maxLength":20000},"next_step":{"type":"string","nullable":true,"maxLength":500},"next_step_due_at":{"type":"string","format":"date","nullable":true},"rationale":{"type":"string","maxLength":2000},"confidence":{"type":"integer","minimum":1,"maximum":5}}}}}},"responses":{"200":{"$ref":"#/components/responses/ProposalReplayed"},"201":{"$ref":"#/components/responses/ProposalCreated"},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/agents/proposals/person-role":{"post":{"summary":"Propose attaching a person to an entity in a specific role","description":"Connect an existing person to an existing entity via person_entity_roles (Track P). On accept, inserts a person_entity_roles row. Use `start_date`/`end_date` for historical roles (e.g. an ex-CEO who left in 2024). For brand-new people, submit /agents/proposals/person first.","parameters":[{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["person_slug_or_id","entity_slug_or_id","role_kind"],"properties":{"person_slug_or_id":{"type":"string"},"entity_slug_or_id":{"type":"string"},"role_kind":{"type":"string","enum":["founder","ceo","cfo","head_of_treasury","board","investor","advisor","employee","ex_employee","partner_contact"]},"role_label":{"type":"string","nullable":true,"maxLength":200,"description":"Free-text refinement, e.g. 'Head of Treasury, EMEA'."},"is_primary":{"type":"boolean"},"start_date":{"type":"string","format":"date","nullable":true},"end_date":{"type":"string","format":"date","nullable":true},"rationale":{"type":"string","maxLength":2000},"confidence":{"type":"integer","minimum":1,"maximum":5}}}}}},"responses":{"200":{"$ref":"#/components/responses/ProposalReplayed"},"201":{"$ref":"#/components/responses/ProposalCreated"},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/agents/proposals/segment-lore-update":{"post":{"summary":"Propose an update to a SEGMENT's Dossier narrative","description":"Update the qualitative Dossier body for an ecosystem segment (mining, custody, treasuries, lightning, etc.). Macro twin of /agents/proposals/lore-update. Submit the FULL new body (not a diff). The accept step replaces the canonical segment dossier body and preserves the prior state in segment_lore_versions. Always read the existing dossier via GET /segments/{slug}?include=lore before proposing, and submit additive edits.","parameters":[{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["target_segment_slug","proposed_body","diff_summary"],"properties":{"target_segment_slug":{"type":"string","description":"Segment slug. Must match a slug from GET /v1/segments."},"proposed_body":{"type":"string","maxLength":50000,"description":"Full new segment dossier body in markdown."},"diff_summary":{"type":"string","maxLength":200,"description":"One-line description of what changed. Shown on the inbox card."},"rationale":{"type":"string","maxLength":2000,"description":"Brief justification (sources, conversations, observations)."},"confidence":{"type":"integer","minimum":1,"maximum":5}}}}}},"responses":{"200":{"$ref":"#/components/responses/ProposalReplayed"},"201":{"$ref":"#/components/responses/ProposalCreated"},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}}}}}