{"openapi":"3.1.0","info":{"title":"JDG Capital Opportunity Intake API","version":"1.0.0","description":"Preview-first, explicitly approved acquisition opportunity intake. Previewing never writes opportunity records."},"servers":[{"url":"https://os.jdgcapitalgroup.com"}],"security":[{"bearerAuth":[]}],"paths":{"/api/v1/opportunity-intakes/preview":{"post":{"summary":"Validate and preview an approved intake batch","operationId":"previewOpportunityIntake","description":"Preview an explicitly approved intake. approval_timestamp must be the real approval instant and not future. Preserve preview_id, expires_at, can_confirm, and possible_duplicates for confirmation.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/IntakeRequest"},"example":{"request_id":"research-2026-07-19-001","source":"authorized-ai-research","submitted_by":{"id":"research-agent","email":"research-agent@example.com","name":"Research Agent","type":"api_client"},"approved_by":{"id":"reviewer","email":"reviewer@example.com","name":"Reviewer","type":"user"},"approval_timestamp":"2026-07-19T18:00:00Z","opportunities":[{"external_id":"platform:12345","business_name":"Acme Services","explicitly_approved":true,"listing_url":"https://example.com/listing/12345","asking_price":1200000,"revenue":null,"sde":350000,"provenance_type":"listing_reported","research_date":"2026-07-19"}]}}}},"responses":{"200":{"description":"Complete confirmation handoff; no opportunity records were written. Preserve this response until confirmation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PreviewResponse"},"example":{"preview_id":"1d375f5a-e220-4cd2-915e-400c8a9f3080","request_id":"research-2026-07-19-001","expires_at":"2026-07-19T22:27:02.079Z","can_confirm":true,"inserts":[{"external_id":"platform:12345","target_id":null,"target_external_id":null,"match_method":null}],"updates":[],"merges":[],"unchanged":[],"possible_duplicates":[],"warnings":[],"rejected_records":[],"field_level_changes":[],"underwriting":[]}}},"links":{"confirmOpportunityIntake":{"operationId":"confirmOpportunityIntake","parameters":{"previewId":"$response.body#/preview_id"},"requestBody":{"confirm":true},"description":"Pass the exact preview_id from this response. Confirm only before expires_at and only when can_confirm is true; resolve every possible_duplicates entry when present."}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"409":{"$ref":"#/components/responses/Conflict"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/api/v1/opportunity-intakes/{previewId}/confirm":{"post":{"summary":"Explicitly confirm a previewed operation","operationId":"confirmOpportunityIntake","description":"Use the exact unexpired preview_id returned by previewOpportunityIntake. If possible_duplicates was non-empty, include an explicit resolution for every ambiguous external ID.","parameters":[{"name":"previewId","in":"path","required":true,"description":"Exact preview_id returned by previewOpportunityIntake.","schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConfirmRequest"},"example":{"confirm":true,"duplicate_resolutions":{"platform:12345":{"target_id":42}}}}}},"responses":{"200":{"description":"Batch committed transactionally.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConfirmResponse"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"},"429":{"$ref":"#/components/responses/RateLimited"}}}}},"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JDG intake API token","description":"Use a token with opportunities:intake. Browser session cookies are not accepted."}},"schemas":{"JsonValue":{"oneOf":[{"type":"string"},{"type":"number"},{"type":"boolean"},{"type":"null"},{"type":"array","items":{"oneOf":[{"type":"string"},{"type":"number"},{"type":"boolean"},{"type":"null"},{"type":"object","properties":{},"additionalProperties":true}]}},{"type":"object","properties":{},"additionalProperties":true}]},"ActionIdentity":{"type":"object","additionalProperties":false,"required":["id"],"description":"A stable actor identity. ChatGPT Actions must send id; an email may also be supplied. The API runtime also accepts email-only identities.","properties":{"id":{"type":"string","minLength":1,"description":"Stable non-empty identity used for intake audit history.","example":"research-agent"},"email":{"type":"string","format":"email","example":"research-agent@example.com"},"name":{"type":"string"},"type":{"type":"string"}}},"FieldProvenance":{"type":"object","additionalProperties":false,"properties":{"type":{"type":"string","enum":["listing_reported","broker_reported","cim_reported","buyer_adjusted","inferred","verified"]},"source_url":{"type":["string","null"],"format":"uri"},"research_date":{"type":["string","null"],"format":"date"},"confidence":{"oneOf":[{"type":"number","minimum":0,"maximum":1},{"type":"string","enum":["low","medium","high"]},{"type":"null"}],"description":"A 0–1 confidence value. The labels low, medium, and high are also accepted and normalized by the API."}}},"Opportunity":{"type":"object","additionalProperties":false,"required":["external_id","business_name","explicitly_approved"],"properties":{"external_id":{"type":"string","example":"bizbuysell:12345"},"business_name":{"type":"string","example":"Acme Services"},"explicitly_approved":{"const":true},"listing_url":{"type":["string","null"],"format":"uri"},"listing_id":{"type":["string","null"]},"source_platform":{"type":["string","null"]},"source_document_id":{"type":["string","null"]},"industry":{"type":["string","null"]},"location":{"type":["string","null"]},"asking_price":{"type":["number","null"]},"revenue":{"type":["number","null"]},"sde":{"type":["number","null"]},"ebitda":{"type":["number","null"]},"employees":{"type":["number","null"]},"years_in_business":{"type":["number","null"]},"broker_information":{"type":["object","null"],"properties":{},"additionalProperties":{"$ref":"#/components/schemas/JsonValue"}},"summary":{"type":["string","null"]},"investment_thesis":{"type":["string","null"]},"risks":{"type":["string","null"]},"buy_box_score":{"type":["number","null"]},"recommended_stage":{"type":["string","null"],"enum":["idea","broker_email","received_cim","broker_call","loi_submitted","seller_meeting","loi_signed","contract_negotiations","contract_signed","closed_acquired","business_transitioned","on_hold","passed","archived",null],"description":"Canonical CRM stage ID. Use idea for an initial-review opportunity."},"research_confidence":{"oneOf":[{"type":"number","minimum":0,"maximum":1},{"type":"string","enum":["low","medium","high"]},{"type":"null"}],"description":"A 0–1 confidence value. The labels low, medium, and high are also accepted and normalized by the API."},"bank_financing_pct":{"type":"number","minimum":0,"maximum":100,"default":80,"description":"bank_financing_pct native underwriting value. Omit on update to preserve the CRM value."},"seller_financing_pct":{"type":"number","minimum":0,"maximum":100,"default":10,"description":"seller_financing_pct native underwriting value. Omit on update to preserve the CRM value."},"buyer_down_payment_pct":{"type":"number","minimum":0,"maximum":100,"default":10,"description":"buyer_down_payment_pct native underwriting value. Omit on update to preserve the CRM value."},"sba_term_years":{"type":"integer","minimum":1,"default":10,"description":"sba_term_years native underwriting value. Omit on update to preserve the CRM value."},"sba_interest_rate":{"type":"number","minimum":0,"maximum":100,"default":9.5,"description":"sba_interest_rate native underwriting value. Omit on update to preserve the CRM value."},"sba_loan_amount":{"type":["number","null"],"minimum":0,"default":null,"description":"sba_loan_amount native underwriting value. Omit on update to preserve the CRM value; explicit null clears it."},"sba_loan_amount_overridden":{"type":"boolean","default":false,"description":"sba_loan_amount_overridden native underwriting value. Omit on update to preserve the CRM value."},"seller_note_term_years":{"type":"integer","minimum":1,"default":7,"description":"seller_note_term_years native underwriting value. Omit on update to preserve the CRM value."},"seller_note_interest_rate":{"type":"number","minimum":0,"maximum":100,"default":7,"description":"seller_note_interest_rate native underwriting value. Omit on update to preserve the CRM value."},"seller_note_standby_years":{"type":"integer","minimum":0,"default":2,"description":"seller_note_standby_years native underwriting value. Omit on update to preserve the CRM value."},"seller_note_amount":{"type":["number","null"],"minimum":0,"default":null,"description":"seller_note_amount native underwriting value. Omit on update to preserve the CRM value; explicit null clears it."},"seller_note_amount_overridden":{"type":"boolean","default":false,"description":"seller_note_amount_overridden native underwriting value. Omit on update to preserve the CRM value."},"tax_rate":{"type":"number","minimum":0,"maximum":100,"default":20,"description":"tax_rate native underwriting value. Omit on update to preserve the CRM value."},"cash_reserve_rate":{"type":"number","minimum":0,"maximum":100,"default":10,"description":"cash_reserve_rate native underwriting value. Omit on update to preserve the CRM value."},"working_capital":{"type":["number","null"],"minimum":0,"default":null,"description":"working_capital native underwriting value. Omit on update to preserve the CRM value; explicit null clears it."},"working_capital_overridden":{"type":"boolean","default":false,"description":"working_capital_overridden native underwriting value. Omit on update to preserve the CRM value."},"transaction_costs":{"type":["number","null"],"minimum":0,"default":null,"description":"transaction_costs native underwriting value. Omit on update to preserve the CRM value; explicit null clears it."},"transaction_costs_overridden":{"type":"boolean","default":false,"description":"transaction_costs_overridden native underwriting value. Omit on update to preserve the CRM value."},"initial_capex":{"type":"number","minimum":0,"default":0,"description":"initial_capex native underwriting value. Omit on update to preserve the CRM value."},"other_project_costs":{"type":"number","minimum":0,"default":0,"description":"other_project_costs native underwriting value. Omit on update to preserve the CRM value."},"source_facts":{"type":["array","object"],"properties":{},"items":{"$ref":"#/components/schemas/JsonValue"},"additionalProperties":{"$ref":"#/components/schemas/JsonValue"}},"research_date":{"type":["string","null"],"format":"date"},"provenance_type":{"type":"string","enum":["listing_reported","broker_reported","cim_reported","buyer_adjusted","inferred","verified"]},"provenance":{"type":"object","properties":{"business_name":{"$ref":"#/components/schemas/FieldProvenance"},"industry":{"$ref":"#/components/schemas/FieldProvenance"},"location":{"$ref":"#/components/schemas/FieldProvenance"},"asking_price":{"$ref":"#/components/schemas/FieldProvenance"},"revenue":{"$ref":"#/components/schemas/FieldProvenance"},"sde":{"$ref":"#/components/schemas/FieldProvenance"},"ebitda":{"$ref":"#/components/schemas/FieldProvenance"},"employees":{"$ref":"#/components/schemas/FieldProvenance"},"years_in_business":{"$ref":"#/components/schemas/FieldProvenance"},"listing_url":{"$ref":"#/components/schemas/FieldProvenance"},"summary":{"$ref":"#/components/schemas/FieldProvenance"},"investment_thesis":{"$ref":"#/components/schemas/FieldProvenance"},"risks":{"$ref":"#/components/schemas/FieldProvenance"},"buy_box_score":{"$ref":"#/components/schemas/FieldProvenance"},"recommended_stage":{"$ref":"#/components/schemas/FieldProvenance"},"research_confidence":{"$ref":"#/components/schemas/FieldProvenance"},"research_date":{"$ref":"#/components/schemas/FieldProvenance"},"source_platform":{"$ref":"#/components/schemas/FieldProvenance"},"listing_id":{"$ref":"#/components/schemas/FieldProvenance"},"source_document_id":{"$ref":"#/components/schemas/FieldProvenance"},"broker_information":{"$ref":"#/components/schemas/FieldProvenance"},"source_facts":{"$ref":"#/components/schemas/FieldProvenance"},"bank_financing_pct":{"$ref":"#/components/schemas/FieldProvenance"},"seller_financing_pct":{"$ref":"#/components/schemas/FieldProvenance"},"buyer_down_payment_pct":{"$ref":"#/components/schemas/FieldProvenance"},"sba_term_years":{"$ref":"#/components/schemas/FieldProvenance"},"sba_interest_rate":{"$ref":"#/components/schemas/FieldProvenance"},"sba_loan_amount":{"$ref":"#/components/schemas/FieldProvenance"},"sba_loan_amount_overridden":{"$ref":"#/components/schemas/FieldProvenance"},"seller_note_term_years":{"$ref":"#/components/schemas/FieldProvenance"},"seller_note_interest_rate":{"$ref":"#/components/schemas/FieldProvenance"},"seller_note_standby_years":{"$ref":"#/components/schemas/FieldProvenance"},"seller_note_amount":{"$ref":"#/components/schemas/FieldProvenance"},"seller_note_amount_overridden":{"$ref":"#/components/schemas/FieldProvenance"},"tax_rate":{"$ref":"#/components/schemas/FieldProvenance"},"cash_reserve_rate":{"$ref":"#/components/schemas/FieldProvenance"},"working_capital":{"$ref":"#/components/schemas/FieldProvenance"},"working_capital_overridden":{"$ref":"#/components/schemas/FieldProvenance"},"transaction_costs":{"$ref":"#/components/schemas/FieldProvenance"},"transaction_costs_overridden":{"$ref":"#/components/schemas/FieldProvenance"},"initial_capex":{"$ref":"#/components/schemas/FieldProvenance"},"other_project_costs":{"$ref":"#/components/schemas/FieldProvenance"}},"additionalProperties":false,"description":"Optional field-level provenance keyed only by supported opportunity field names."}}},"IntakeRequest":{"type":"object","additionalProperties":false,"required":["request_id","source","submitted_by","approved_by","approval_timestamp","opportunities"],"properties":{"request_id":{"type":"string","minLength":8},"source":{"type":"string"},"submitted_by":{"$ref":"#/components/schemas/ActionIdentity"},"approved_by":{"$ref":"#/components/schemas/ActionIdentity"},"approval_timestamp":{"type":"string","format":"date-time","description":"Exact instant when the named approver explicitly approved these records. Must be at or before request time. Use ISO 8601 with UTC Z or the correct numeric offset; never label local wall-clock time as UTC or invent a future value.","example":"2026-07-19T12:30:00-07:00"},"opportunities":{"type":"array","minItems":1,"items":{"$ref":"#/components/schemas/Opportunity"}}}},"PlanSummary":{"type":"object","additionalProperties":false,"required":["external_id","target_id","target_external_id","match_method"],"properties":{"external_id":{"type":"string"},"target_id":{"type":["string","null"],"description":"PostgreSQL bigint identifier serialized as a JSON string."},"target_external_id":{"type":["string","null"]},"match_method":{"type":["string","null"]}}},"DuplicateCandidate":{"type":"object","additionalProperties":false,"required":["id","external_id","business_name","listing_url"],"properties":{"id":{"type":"string","description":"PostgreSQL bigint identifier serialized as a JSON string."},"external_id":{"type":["string","null"]},"business_name":{"type":["string","null"]},"listing_url":{"type":["string","null"],"format":"uri"}}},"PossibleDuplicate":{"type":"object","additionalProperties":false,"required":["external_id","match_method","candidates"],"description":"An ambiguous match that blocks confirmation until duplicate_resolutions contains this external_id.","properties":{"external_id":{"type":"string","description":"Key to use in ConfirmRequest.duplicate_resolutions."},"match_method":{"type":["string","null"]},"candidates":{"type":"array","minItems":2,"items":{"$ref":"#/components/schemas/DuplicateCandidate"}}}},"IntakeWarning":{"type":"object","additionalProperties":false,"required":["code","external_id","field","message"],"properties":{"code":{"type":"string"},"external_id":{"type":["string","null"]},"field":{"type":["string","null"]},"message":{"type":"string"}}},"RejectedRecord":{"type":"object","additionalProperties":false,"required":["external_id","reason","details"],"properties":{"external_id":{"type":["string","null"]},"reason":{"type":["string","null"]},"details":{"type":"array","items":{"type":"string"}}}},"FieldLevelChange":{"type":"object","additionalProperties":false,"required":["external_id","field","from","to","provenance"],"properties":{"external_id":{"type":"string"},"field":{"type":"string"},"from":{"$ref":"#/components/schemas/JsonValue"},"to":{"$ref":"#/components/schemas/JsonValue"},"provenance":{"type":["string","null"]}}},"UnderwritingPreview":{"type":"object","additionalProperties":false,"required":["external_id","outputs"],"properties":{"external_id":{"type":"string"},"outputs":{"type":"object","properties":{},"additionalProperties":{"$ref":"#/components/schemas/JsonValue"}}}},"PreviewResponse":{"type":"object","additionalProperties":false,"description":"Stateful handoff from preview to confirmation. The connector must preserve this response through the explicit user-confirmation step.","required":["preview_id","request_id","can_confirm","inserts","updates","merges","unchanged","possible_duplicates","warnings","rejected_records","field_level_changes","underwriting","expires_at"],"properties":{"preview_id":{"type":"string","format":"uuid","description":"Opaque server-generated identifier. Preserve exactly and pass as confirmOpportunityIntake.previewId; never invent or reuse a request_id here."},"request_id":{"type":"string","description":"Client idempotency key; this is not the confirmation previewId."},"can_confirm":{"type":"boolean","description":"Confirmation is allowed only when true. False means possible_duplicates requires explicit resolution."},"inserts":{"type":"array","items":{"$ref":"#/components/schemas/PlanSummary"}},"updates":{"type":"array","items":{"$ref":"#/components/schemas/PlanSummary"}},"merges":{"type":"array","items":{"$ref":"#/components/schemas/PlanSummary"}},"unchanged":{"type":"array","items":{"$ref":"#/components/schemas/PlanSummary"}},"possible_duplicates":{"type":"array","description":"Ambiguous matches to preserve and resolve before confirmation. Each external_id must be present in duplicate_resolutions.","items":{"$ref":"#/components/schemas/PossibleDuplicate"}},"warnings":{"type":"array","items":{"$ref":"#/components/schemas/IntakeWarning"}},"rejected_records":{"type":"array","items":{"$ref":"#/components/schemas/RejectedRecord"}},"field_level_changes":{"type":"array","items":{"$ref":"#/components/schemas/FieldLevelChange"}},"underwriting":{"type":"array","items":{"$ref":"#/components/schemas/UnderwritingPreview"}},"expires_at":{"type":"string","format":"date-time","description":"Confirmation deadline. Do not call confirmOpportunityIntake after this timestamp."},"status":{"type":"string"}}},"DuplicateResolution":{"type":"object","additionalProperties":false,"description":"Resolve an ambiguous match by selecting one returned candidate target_id or explicitly rejecting the incoming record.","properties":{"target_id":{"type":"integer","description":"Candidate id selected from PossibleDuplicate.candidates."},"action":{"type":"string","const":"reject"}},"oneOf":[{"required":["target_id"]},{"required":["action"]}]},"ConfirmRequest":{"type":"object","additionalProperties":false,"required":["confirm"],"properties":{"confirm":{"type":"boolean","const":true,"description":"Explicit confirmation gate."},"duplicate_resolutions":{"type":"object","properties":{},"description":"Required when the preserved preview response contained possible_duplicates. Keys are ambiguous external_id values.","additionalProperties":{"$ref":"#/components/schemas/DuplicateResolution"}}}},"ConfirmationCounts":{"type":"object","additionalProperties":false,"required":["inserted","updated","unchanged","rejected"],"properties":{"inserted":{"type":"integer","minimum":0},"updated":{"type":"integer","minimum":0},"unchanged":{"type":"integer","minimum":0},"rejected":{"type":"integer","minimum":0}}},"ConfirmResponse":{"type":"object","additionalProperties":false,"required":["preview_id","status","counts","underwriting_recalculated"],"properties":{"preview_id":{"type":"string","format":"uuid"},"status":{"type":"string","const":"confirmed"},"idempotent_replay":{"type":"boolean"},"counts":{"$ref":"#/components/schemas/ConfirmationCounts"},"underwriting_recalculated":{"type":"integer","minimum":0}}},"ValidationIssueGroup":{"type":"object","additionalProperties":false,"required":["issues"],"properties":{"issues":{"type":"array","minItems":1,"items":{"type":"string"}}}},"Error":{"type":"object","additionalProperties":false,"required":["error"],"properties":{"error":{"type":"string"},"code":{"type":"string"},"details":{"type":"array","items":{"type":"string"}},"rejected_records":{"type":"array","items":{"$ref":"#/components/schemas/ValidationIssueGroup"}},"correlation_id":{"type":"string"}},"example":{"error":"Token requires scope opportunities:intake.","code":"insufficient_scope","correlation_id":"8f12d62f-0eef-4c8e-93d7-9ff23454cd01"}}},"responses":{"BadRequest":{"description":"Invalid or unapproved request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Unauthorized":{"description":"Missing, invalid, expired, or revoked token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Forbidden":{"description":"Token lacks the required scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"NotFound":{"description":"Preview not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Conflict":{"description":"Idempotency conflict, duplicate resolution required, or already resolved preview.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"RateLimited":{"description":"Rate limit exceeded.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}}