{
  "version": "v1",
  "generated_at": "2026-08-29T06:23:31.412Z",
  "basePath": "/api/v1",
  "auth": {
    "header": "X-API-Key",
    "scopes": [
      "search",
      "profiles-read",
      "profiles-write",
      "enrich",
      "communications",
      "contacts-read",
      "contacts-write",
      "contacts-delegate-resolve"
    ]
  },
  "pagination": {
    "limitParam": "limit",
    "offsetParam": "offset"
  },
  "limits": {
    "resultsSnapshotMax": 25,
    "previewEnrichable": false
  },
  "endpoints": [
    {
      "method": "GET",
      "path": "/api/v1/credits",
      "category": "credits",
      "description": "Fetch the shared account credit-pool summary for the authenticated API key, current-key usage counters, the active search rate card, and billing semantics for each public API operation.",
      "request": {
        "range": "string (optional, 7d|14d|30d|90d|today|all_time)",
        "start_date": "string (optional, ISO date/time)",
        "end_date": "string (optional, ISO date/time)"
      },
      "response": {
        "success": "boolean",
        "owner_user_id": "uuid",
        "current_api_key": "CurrentApiKey",
        "current_key_usage": "CurrentApiKeyUsage",
        "account_credit_pool": "object",
        "rate_card": "object",
        "billing_semantics": "CreditBillingSemanticsEntry[]",
        "notes": "string[]"
      }
    },
    {
      "method": "GET",
      "path": "/api/v1/credits/status",
      "category": "credits",
      "description": "Lightweight rolling-window credit status for the authenticated API key owner. Returns { tier, limit, used, remaining, window_start, window_days, reset_at, as_of }. Mirrors the X-Carl-Credits-* response headers emitted on every authenticated call. Safe to poll — remains reachable at or over the credit ceiling.",
      "response": {
        "tier": "string (free|starter|starter_annual|pro|annual|team)",
        "limit": "number|null",
        "used": "number",
        "remaining": "number|null",
        "window_start": "string|null (RFC 3339; null when no usage in the current window)",
        "window_days": "number",
        "reset_at": "string|null (RFC 3339; null when no usage in the current window)",
        "as_of": "string (RFC 3339)"
      }
    },
    {
      "method": "GET",
      "path": "/api/v1/contacts/reconciliation/schema",
      "scopes": [
        "contacts-read",
        "search"
      ],
      "category": "contacts",
      "description": "Return the public contact reconciliation row schema, supported modes, review actions, and batch limits for agent-assisted spreadsheet reconciliation. Existing MCP connector keys with the legacy search scope can use this read-only compatibility path.",
      "request": {
        "delegate_user_id": "uuid (optional)"
      },
      "response": {
        "success": "boolean",
        "tool": "contacts_reconcile",
        "source_type": "agent_reconciliation_sheet",
        "row_schema": "object",
        "modes": "string[]",
        "review_actions": "string[]",
        "notes": "string[]"
      }
    },
    {
      "method": "POST",
      "path": "/api/v1/contacts/delegate-resolve",
      "scopes": [
        "contacts-delegate-resolve"
      ],
      "category": "contacts",
      "description": "API-key-only batch contact resolver for integrations that need to resolve contacts from the perspective of a supplied delegate person instead of the API key owner. The delegate is required and can be supplied by Super Carl id or LinkedIn URL/username. The endpoint accepts up to 100 contacts per call and returns compact resolved-profile projections plus evidence/reasons. It is intentionally not exposed through MCP or OAuth connector scopes.",
      "request": {
        "delegate": "{ user_id | super_carl_id | linkedin_url | linkedin_username } (required)",
        "contacts": "DelegateContactInput[] (required, max 100; supports name, emails, phone_numbers, organization_names, job_titles, address/location, LinkedIn URL)",
        "options": "object (optional: dry_run, persist_evidence, include_email, include_email_enrichment, force_email_enrichment, email_enrichment_provider, email_minimum_confidence, fields, include_experiences, include_score_breakdown, max_candidates_per_contact, contact_concurrency)"
      },
      "response": {
        "success": "boolean",
        "mode": "delegate_contact_resolve",
        "dry_run": "boolean",
        "persisted_evidence_count": "number",
        "audit_run_id": "uuid|null",
        "billing": "{ charged, billable_preview_count, billable_resolve_count, billable_email_enrichment_count, preview_credits_charged, resolve_credits_charged, email_enrichment_credits_charged, total_credits_charged }",
        "delegate": "ResolvedDelegate",
        "summary": "{ requested, resolved, needs_review, unresolved }",
        "results": "DelegateContactResolveResult[] (includes selected_candidate_user_id, selected_profile projection including email when available/requested, email_resolution, evidence, candidates, warnings)"
      },
      "notes": [
        "This route rejects OAuth/MCP-authenticated calls even if a token carries compatible scopes; use X-API-Key.",
        "Performance: each request accepts up to 100 contacts and resolves up to 5 contacts concurrently by default. contact_concurrency can tune the per-request worker count from 1 to 10.",
        "Billing: internal contact resolution and dry-run previews remain telemetry-only. Provider-backed email enrichment is charged only after an explicit user opt-in at actual provider cost converted at $0.099 per credit; cached, known, and no-find results cost 0.",
        "Email projection is included by default when a cached/known email exists. Provider email enrichment runs only when include_email_enrichment=true. Set email_minimum_confidence to require a stronger returned email quality such as validated, sourced, or verified.",
        "Evidence persistence is opt-in with options.persist_evidence=true and options.dry_run=false. Persisted phone/email signals are hashed for future peer-evidence support.",
        "Result evidence omits peer owner identities and support counts."
      ]
    },
    {
      "method": "POST",
      "path": "/api/v1/contacts/reconciliation/runs",
      "scopes": [
        "contacts-read",
        "search"
      ],
      "category": "contacts",
      "description": "Create a bounded contact reconciliation run for a user-supplied spreadsheet or agent-normalized contact sheet. This sets up workflow/audit state only; applying changes still requires contacts-write.",
      "request": {
        "delegate_user_id": "uuid (optional)",
        "source_label": "string (optional)",
        "options": "object (optional; allow_identity_resolution, identity_resolution_limit)"
      },
      "response": {
        "success": "boolean",
        "owner_user_id": "uuid",
        "acting_user_id": "uuid",
        "run": "ContactReconciliationRun"
      }
    },
    {
      "method": "POST",
      "path": "/api/v1/contacts/reconciliation/runs/:runId/batches/preview",
      "scopes": [
        "contacts-read",
        "search"
      ],
      "category": "contacts",
      "description": "Preview up to 100 normalized spreadsheet rows before applying them. Preview writes audit rows for the reconciliation run but does not mutate contact state, and remains available to existing MCP connector keys with the legacy search scope.",
      "request": {
        "delegate_user_id": "uuid (optional)",
        "batch_index": "number (optional)",
        "rows": "ContactReconciliationRow[] (required, max 100)",
        "options": "object (optional)"
      },
      "response": {
        "success": "boolean",
        "run": "ContactReconciliationRun",
        "batch_id": "uuid",
        "summary": "object",
        "rows": "ContactReconciliationPlannedRow[]"
      }
    },
    {
      "method": "POST",
      "path": "/api/v1/contacts/reconciliation/runs/:runId/batches",
      "scopes": [
        "contacts-write"
      ],
      "category": "contacts",
      "description": "Apply a reviewed batch of up to 100 normalized spreadsheet rows. Likely matches remain candidates until a later explicit confirm action.",
      "request": {
        "delegate_user_id": "uuid (optional)",
        "batch_index": "number (optional)",
        "rows": "ContactReconciliationRow[] (required, max 100)",
        "options": "object (optional; allow_identity_resolution only affects apply)",
        "user_confirmed": "boolean (required true)"
      },
      "response": {
        "success": "boolean",
        "run": "ContactReconciliationRun",
        "batch_id": "uuid",
        "summary": "object",
        "rows": "ContactReconciliationAppliedRow[]"
      }
    },
    {
      "method": "GET",
      "path": "/api/v1/contacts/reconciliation/runs/:runId",
      "scopes": [
        "contacts-read",
        "search"
      ],
      "category": "contacts",
      "description": "Read reconciliation run status, aggregate row summary, and recent batch metadata.",
      "request": {
        "delegate_user_id": "uuid (optional)"
      },
      "response": {
        "success": "boolean",
        "run": "ContactReconciliationRun",
        "summary": "object",
        "batches": "ContactReconciliationBatch[]"
      }
    },
    {
      "method": "POST",
      "path": "/api/v1/contacts/reconciliation/runs/:runId/finalize",
      "scopes": [
        "contacts-write"
      ],
      "category": "contacts",
      "description": "Finalize a reconciliation run after reviewed batches are applied.",
      "request": {
        "delegate_user_id": "uuid (optional)",
        "user_confirmed": "boolean (required true)"
      },
      "response": {
        "success": "boolean",
        "run": "ContactReconciliationRun",
        "summary": "object"
      }
    },
    {
      "method": "GET",
      "path": "/api/v1/contacts/reconciliation/review",
      "scopes": [
        "contacts-read",
        "search"
      ],
      "category": "contacts",
      "description": "List contact review entities in the same buckets exposed by the incoming/review tab, including likely_match, needs_review, unresolved, approved, and ignored.",
      "request": {
        "delegate_user_id": "uuid (optional)",
        "bucket": "string (optional, approved|likely_match|needs_review|unresolved|ignored)",
        "limit": "number (optional, max 100)",
        "offset": "number (optional)",
        "response_verbosity": "string (optional, compact|minimal|detailed; use compact for 100-row triage pages)"
      },
      "response": {
        "success": "boolean",
        "items": "ContactReviewEntity[]",
        "page": "object"
      }
    },
    {
      "method": "POST",
      "path": "/api/v1/contacts/reconciliation/review/bulk",
      "scopes": [
        "contacts-write"
      ],
      "category": "contacts",
      "description": "Apply up to 100 explicit review actions in one call. Bulk confirm can use entity_ids alone to confirm each row's stored proposed/top candidate, or items with per-row candidate_user_id overrides.",
      "request": {
        "delegate_user_id": "uuid (optional)",
        "action": "confirm_candidate|reject_candidate|mark_needs_review|ignore_entity|restore_entity",
        "entity_ids": "uuid[] (optional, max 100)",
        "items": "array (optional, max 100; entity_id, candidate_user_id, candidate_snapshot)",
        "user_confirmed": "boolean (required true)"
      },
      "response": {
        "success": "boolean",
        "requested_count": "number",
        "succeeded_count": "number",
        "failed_count": "number",
        "results": "BulkReviewResult[]"
      }
    },
    {
      "method": "GET",
      "path": "/api/v1/contacts/reconciliation/review/:entityId/candidates",
      "scopes": [
        "contacts-read",
        "search"
      ],
      "category": "contacts",
      "description": "Fetch candidate Super Carl user matches for one contact review entity before confirming or rejecting.",
      "request": {
        "delegate_user_id": "uuid (optional)",
        "query": "string (optional)",
        "limit": "number (optional, max 25)"
      },
      "response": {
        "success": "boolean",
        "entity": "ContactReviewEntity",
        "candidates": "ContactReviewCandidate[]"
      }
    },
    {
      "method": "POST",
      "path": "/api/v1/contacts/reconciliation/review/:entityId/confirm",
      "scopes": [
        "contacts-write"
      ],
      "category": "contacts",
      "description": "Confirm one specific candidate user for a contact review entity. This is the explicit promotion step for likely matches.",
      "request": {
        "delegate_user_id": "uuid (optional)",
        "candidate_user_id": "uuid",
        "candidate_snapshot": "object (optional)",
        "user_confirmed": "boolean (required true)"
      },
      "response": {
        "success": "boolean",
        "entity": "ContactReviewEntity"
      }
    },
    {
      "method": "POST",
      "path": "/api/v1/contacts/reconciliation/review/:entityId/:action",
      "scopes": [
        "contacts-write"
      ],
      "category": "contacts",
      "description": "Review mutation endpoint for needs-review, not-a-match, ignore, and restore actions. These mirror the incoming/review tab controls.",
      "request": {
        "delegate_user_id": "uuid (optional)",
        "action": "path segment: needs-review|not-a-match|ignore|restore",
        "user_confirmed": "boolean (required true)"
      },
      "response": {
        "success": "boolean",
        "entity": "ContactReviewEntity"
      }
    },
    {
      "method": "POST",
      "path": "/api/v2/search/people/query",
      "scopes": [
        "search"
      ],
      "category": "people-search",
      "description": "Run a natural-language people search. The service converts the text to typed filters and returns the applied request with matching people rows.",
      "request": {
        "query": "string (required, max 2000 characters)",
        "limit": "number (optional, 1-25; default 10)",
        "offset": "number (optional, 0-10000; default 0)",
        "network_filter_mode": "boost|filter|ignore|connected_to (optional; default boost)",
        "include_profile_text": "boolean (optional; default false)",
        "delegate_user_id": "uuid (optional)"
      },
      "response": {
        "success": "boolean",
        "contract_version": "\"2\"",
        "request": "object (input_mode and applied_request)",
        "users": "Person[]",
        "cohort_refs": "opaque reusable cross-search references (when present)",
        "applied_relations": "cross-search relations applied to this result (when present)",
        "pagination": "object"
      },
      "notes": [
        "Use this endpoint when the caller has natural-language criteria. Use direct MCP tool filters when the caller already has a typed request.",
        "Returned opaque cohort references can be reused for typed cross-tool composition."
      ]
    },
    {
      "method": "POST",
      "path": "/api/v1/search/people",
      "scopes": [
        "search"
      ],
      "category": "people-search",
      "description": "Run a full people search or direct lookup by LinkedIn username or full LinkedIn profile URL. The description (or query alias) is auto-translated into AdvancedFilters by default; pass filters/search_metadata for explicit structured constraints. New lookups are enriched automatically. Set include_evidence_text=true or include_evidence_json=true to inline profile evidence for eval or LLM ranking workflows. Person rows include requester-relative previous-correspondence fields across synced/API channels when a Super Carl user identity is resolved.",
      "request": {
        "description": "string",
        "query": "string (legacy alias)",
        "keywords": "string|array (deprecated)",
        "limit": "number",
        "offset": "number",
        "linkedin_username": "string (optional)",
        "linkedin_profile_url": "string (optional)",
        "linkedin_url": "string (optional alias for linkedin_profile_url)",
        "search_metadata": "object",
        "filters": "object (optional)",
        "include_evidence": "boolean (optional; defaults to text evidence when true)",
        "include_evidence_text": "boolean (optional)",
        "include_evidence_json": "boolean (optional)",
        "evidence_format": "string (optional, none|reasons|text|json|both; reasons builds deterministic light match_reasons)",
        "evidence_text_mode": "string (optional, base|full)",
        "evidence_posts_limit": "number (optional)",
        "defer_enrichment": "boolean (optional; skip enrichment on non-reasons calls)",
        "skip_match_reasons": "boolean (optional; skip match-reason enrichment unless evidence_format=reasons)",
        "delegate_user_id": "uuid (optional)"
      },
      "response": {
        "success": "boolean",
        "search_id": "string",
        "users": "Person[]",
        "pagination": "object",
        "search_metadata": "object",
        "no_results_reason": "string (optional, present when total results are zero and a deterministic reason is available)"
      }
    },
    {
      "method": "POST",
      "path": "/api/v1/communications/capabilities",
      "scopes": [
        "communications"
      ],
      "category": "communications",
      "description": "Resolve the acting user, target identity, and per-channel readiness for Super Carl direct messages, Super Carl invites, Super Carl referrals, Gmail sends, LinkedIn sends, X sends, and Instagram sends.",
      "request": {
        "delegate_user_id": "uuid (optional)",
        "target_user_id": "uuid (optional)",
        "linkedin_profile_url": "string (optional)",
        "linkedin_username": "string (optional)",
        "x_profile_url": "string (optional)",
        "x_username": "string (optional)",
        "instagram_profile_url": "string (optional)",
        "instagram_username": "string (optional)",
        "recipient_email": "string (optional; for Gmail, may be a returned option or a valid user-supplied address)",
        "channels": "string[] (optional; any of supercarl_direct_message, supercarl_invite, supercarl_referral_request, gmail_send, linkedin_send_message, x_send_message, instagram_send_message)"
      },
      "response": {
        "owner_user_id": "uuid",
        "acting_user_id": "uuid",
        "is_delegate": "boolean",
        "resolved_target": "object",
        "channels": "CommunicationChannelCapability[]",
        "supercarl": "object"
      }
    },
    {
      "method": "POST",
      "path": "/api/v1/communications",
      "scopes": [
        "communications"
      ],
      "category": "communications",
      "description": "Create a generic outbound communication record and send, invite, request referral, save a durable draft, or dry-run delivery through one of the supported channels.",
      "request": {
        "delegate_user_id": "uuid (optional)",
        "mode": "\"draft\" (optional; saves without delivery)",
        "draft": "boolean (optional; alias for mode=\"draft\")",
        "channel": "string (one of supercarl_direct_message, supercarl_invite, supercarl_referral_request, gmail_send, linkedin_send_message, x_send_message, instagram_send_message)",
        "target_user_id": "uuid (optional)",
        "linkedin_profile_url": "string (optional)",
        "linkedin_username": "string (optional)",
        "x_profile_url": "string (optional)",
        "x_username": "string (optional)",
        "instagram_profile_url": "string (optional)",
        "instagram_username": "string (optional)",
        "recipient_email": "string (optional; for Gmail, may be a returned option or a valid user-supplied address)",
        "connector_user_id": "uuid (optional; required for supercarl_referral_request)",
        "message": "string",
        "subject": "string (required for gmail_send)",
        "dry_run": "boolean (optional)",
        "idempotency_key": "string (optional)",
        "context": "object (optional; structured context for generation or audit metadata)",
        "wait_ms": "number (optional; wait up to this many milliseconds for delivery progress, max 30000)",
        "wait_until": "string (optional, terminal|first_progress; wait condition when wait_ms is set)",
        "webhook_url": "string (optional)",
        "webhook_secret": "string (optional)"
      },
      "response": {
        "id": "uuid",
        "channel": "string",
        "status": "string",
        "result": "object",
        "task": "CommunicationTask|null",
        "reasoning_lookup": "CommunicationReasoningLookup",
        "events": "CommunicationEvent[]",
        "artifacts": "CommunicationArtifact[]"
      }
    },
    {
      "method": "GET",
      "path": "/api/v1/communications/:communicationId",
      "scopes": [
        "communications"
      ],
      "category": "communications",
      "description": "Fetch a communication record with normalized status, recent events, task metadata, reasoning lookup, and artifact URLs.",
      "request": {
        "wait_ms": "number (optional; wait up to this many milliseconds for delivery progress, max 30000)",
        "wait_until": "string (optional, terminal|first_progress; wait condition when wait_ms is set)"
      },
      "response": {
        "id": "uuid",
        "channel": "string",
        "status": "string",
        "result": "object",
        "task": "CommunicationTask|null",
        "reasoning_lookup": "CommunicationReasoningLookup",
        "events": "CommunicationEvent[]",
        "artifacts": "CommunicationArtifact[]",
        "webhook": "CommunicationWebhook"
      }
    },
    {
      "method": "POST",
      "path": "/api/v1/communications/history",
      "scopes": [
        "communications"
      ],
      "category": "communications",
      "description": "Fetch prior visible communication history for a resolved target before drafting or sending.",
      "request": {
        "delegate_user_id": "uuid (optional)",
        "target_user_id": "uuid (optional)",
        "linkedin_profile_url": "string (optional)",
        "linkedin_username": "string (optional)",
        "x_profile_url": "string (optional)",
        "x_username": "string (optional)",
        "instagram_profile_url": "string (optional)",
        "instagram_username": "string (optional)",
        "recipient_email": "string (optional)",
        "channel": "string (optional, all|email|gmail|super_carl|linkedin|x|instagram)",
        "history_fresh": "boolean (optional; request a fresh LinkedIn history refresh when possible)",
        "limit": "number (optional, 1-50)",
        "offset": "number (optional)"
      },
      "response": {
        "success": "boolean",
        "owner_user_id": "uuid",
        "acting_user_id": "uuid",
        "is_delegate": "boolean",
        "resolved_target": "object",
        "target_user_id": "uuid|null",
        "has_prior_send": "boolean",
        "most_recent_send": "object|null",
        "total_count": "number",
        "filtered_count": "number",
        "last_sent_at": "string|null",
        "limit": "number",
        "offset": "number",
        "has_more": "boolean",
        "selected_channel": "string",
        "channel_counts": "object",
        "linkedin_history": "object",
        "entries": "CommunicationHistoryEntry[]"
      }
    },
    {
      "method": "POST",
      "path": "/api/v1/communications/:communicationId/cancel",
      "scopes": [
        "communications"
      ],
      "category": "communications",
      "description": "Cancel a queued or in-progress communication when the underlying channel supports cancellation before dispatch.",
      "request": {
        "reason": "string (optional)"
      },
      "response": {
        "id": "uuid",
        "channel": "string",
        "status": "string",
        "result": "object",
        "task": "CommunicationTask|null",
        "reasoning_lookup": "CommunicationReasoningLookup",
        "events": "CommunicationEvent[]",
        "artifacts": "CommunicationArtifact[]",
        "webhook": "CommunicationWebhook"
      }
    },
    {
      "method": "GET",
      "path": "/api/v1/communications/:communicationId/events",
      "scopes": [
        "communications"
      ],
      "category": "communications",
      "description": "Fetch the append-only communication event log.",
      "request": {
        "after_sequence": "number (optional)",
        "limit": "number (optional)"
      },
      "response": {
        "communication_id": "uuid",
        "events": "CommunicationEvent[]"
      }
    },
    {
      "method": "GET",
      "path": "/api/v1/communications/:communicationId/stream",
      "scopes": [
        "communications"
      ],
      "category": "communications",
      "description": "Server-sent events stream for communication status changes, artifacts, and completion.",
      "response": {
        "content_type": "text/event-stream"
      }
    },
    {
      "method": "GET",
      "path": "/api/v1/communications/:communicationId/artifacts/:filename",
      "scopes": [
        "communications"
      ],
      "category": "communications",
      "description": "Proxy an artifact or screenshot attached to a communication.",
      "response": {
        "content_type": "binary"
      }
    },
    {
      "method": "GET",
      "path": "/api/v1/projects",
      "scopes": [
        "communications"
      ],
      "category": "projects",
      "description": "List active projects for the authenticated owner or delegate. Projects are the public name for assignment workspaces. Pass current_project_id for an MCP/session-bound project that must be surfaced even when generic list filters would hide it.",
      "request": {
        "delegate_user_id": "uuid (optional)",
        "status": "string (optional)",
        "limit": "number (optional)",
        "offset": "number (optional)",
        "include_archived": "boolean (optional)",
        "include_searches": "boolean (optional; include search-only project shells)",
        "current_project_id": "uuid (optional; session-bound project to include even if filtered out)"
      },
      "response": {
        "success": "boolean",
        "owner_user_id": "uuid",
        "acting_user_id": "uuid",
        "is_delegate": "boolean",
        "projects": "Project[]",
        "current_session_project_id": "uuid | null (when current_project_id is supplied)",
        "current_session_project": "Project | null (when current_project_id is supplied)",
        "current_session_project_included": "boolean (when current_project_id is supplied)",
        "current_session_project_reason": "already_in_list | included_from_session_binding | not_found_or_inaccessible",
        "pagination": "object"
      }
    },
    {
      "method": "GET",
      "path": "/api/v1/projects/:projectId",
      "scopes": [
        "communications"
      ],
      "category": "projects",
      "description": "Fetch one project. Set include_targets=true to inline targets, and include_search_results=true to include the search-results cache.",
      "request": {
        "delegate_user_id": "uuid (optional)",
        "include_targets": "boolean (optional)",
        "include_search_results": "boolean (optional)",
        "targets_limit": "number (optional)",
        "targets_offset": "number (optional)"
      },
      "response": {
        "success": "boolean",
        "owner_user_id": "uuid",
        "acting_user_id": "uuid",
        "project": "Project"
      }
    },
    {
      "method": "GET",
      "path": "/api/v1/projects/:projectId/targets",
      "scopes": [
        "communications"
      ],
      "category": "projects",
      "description": "List active included targets for a project, excluding the project owner. This is the standalone API equivalent of the product target list.",
      "request": {
        "delegate_user_id": "uuid (optional)",
        "limit": "number (optional, max 100)",
        "offset": "number (optional)",
        "include_mutuals": "boolean (optional)"
      },
      "response": {
        "success": "boolean",
        "owner_user_id": "uuid",
        "acting_user_id": "uuid",
        "project_id": "uuid",
        "targets": "ProjectTarget[]",
        "pagination": "object"
      }
    },
    {
      "method": "POST",
      "path": "/api/v1/projects/:projectId/targets",
      "scopes": [
        "communications"
      ],
      "category": "projects",
      "description": "Add one or more people to a project shortlist. This is the standalone API equivalent of adding assignment targets in-product.",
      "request": {
        "delegate_user_id": "uuid (optional)",
        "target_user_ids": "uuid[] (required unless target_user_id is provided)",
        "target_user_id": "uuid (optional single target)"
      },
      "response": {
        "success": "boolean",
        "owner_user_id": "uuid",
        "acting_user_id": "uuid",
        "project_id": "uuid",
        "added_targets": "ProjectTarget[]",
        "total_targets": "number"
      }
    },
    {
      "method": "DELETE",
      "path": "/api/v1/projects/:projectId/targets",
      "scopes": [
        "communications"
      ],
      "category": "projects",
      "description": "Remove one or more people from a project shortlist by soft-clearing is_included. Pass remove_all=true only when intentionally clearing the shortlist.",
      "request": {
        "delegate_user_id": "uuid (optional)",
        "target_user_ids": "uuid[] (required unless target_user_id or remove_all is provided)",
        "target_user_id": "uuid (optional single target)",
        "remove_all": "boolean (optional)"
      },
      "response": {
        "success": "boolean",
        "owner_user_id": "uuid",
        "acting_user_id": "uuid",
        "project_id": "uuid",
        "removed_count": "number",
        "results": "TargetRemovalResult[]"
      }
    },
    {
      "method": "GET",
      "path": "/api/v1/projects/:projectId/metrics",
      "scopes": [
        "communications"
      ],
      "category": "projects",
      "description": "Fetch outreach metrics for a project, including response rates, schedule-link click rates, and status-count breakdowns.",
      "request": {
        "delegate_user_id": "uuid (optional)"
      },
      "response": {
        "success": "boolean",
        "project_id": "uuid",
        "total_targets": "number",
        "messages_sent": "number",
        "responses": "number",
        "response_rate": "number|null",
        "target_response_rate": "number|null",
        "schedule_link_clicks": "number",
        "schedule_link_click_rate": "number|null",
        "outreach_status_counts": "object",
        "recipient_status_counts": "object"
      }
    },
    {
      "method": "PATCH",
      "path": "/api/v1/projects/:projectId",
      "scopes": [
        "communications"
      ],
      "category": "projects",
      "description": "Rename a project or update basic project fields such as description, pitch, status, discovery, and engagement mode.",
      "request": {
        "delegate_user_id": "uuid (optional)",
        "title": "string (optional)",
        "description": "string (optional)",
        "pitch": "string (optional)",
        "status": "string (optional)",
        "allow_discovery": "boolean (optional)",
        "engagement_mode": "string (optional)"
      },
      "response": {
        "success": "boolean",
        "project": "Project"
      }
    },
    {
      "method": "PUT",
      "path": "/api/v1/projects/:projectId/templates",
      "scopes": [
        "communications"
      ],
      "category": "projects",
      "description": "Update saved project outreach/referral/engagement templates. Set clear_personalization=true to clear generated target messages for regeneration.",
      "request": {
        "delegate_user_id": "uuid (optional)",
        "email_subject_template": "string|null (optional)",
        "outreach_message_prompt": "string|null (optional)",
        "engagement_meta_prompt": "string|null (optional)",
        "engagement_prompt": "string|null (optional)",
        "referral_intro_prompt": "string|null (optional)",
        "referral_forward_note_prompt": "string|null (optional)",
        "clear_personalization": "boolean (optional)"
      },
      "response": {
        "success": "boolean",
        "project": "Project"
      }
    },
    {
      "method": "POST",
      "path": "/api/v1/projects/:projectId/templates/generate",
      "scopes": [
        "communications"
      ],
      "category": "projects",
      "description": "Generate or regenerate a saved project template against project context. Supported template_type values include email_subject_template, outreach_message_prompt, engagement_meta_prompt, engagement_prompt, pitch, referral_intro_prompt, referral_forward_note_prompt, and generalize_message_to_template.",
      "request": {
        "delegate_user_id": "uuid (optional)",
        "template_type": "string",
        "user_input": "string (optional)",
        "message": "string (required for generalize_message_to_template)"
      },
      "response": {
        "success": "boolean",
        "project": "Project",
        "generated_field": "string (template-specific field, e.g. outreach_message_prompt)"
      }
    },
    {
      "method": "POST",
      "path": "/api/v1/projects/:projectId/messages/generate",
      "scopes": [
        "communications"
      ],
      "category": "projects",
      "description": "Generate personalized target messages against saved project templates. This drafts/generates messages; it does not send them.",
      "request": {
        "delegate_user_id": "uuid (optional)",
        "target_ids": "uuid[] (optional assignment target row ids; omit to generate for all targets needing messages)",
        "target_user_id": "uuid (optional; generate for one target user)",
        "persist_target": "boolean (optional; default true for target_user_id)"
      },
      "response": {
        "success": "boolean",
        "generated_count": "number",
        "targets": "ProjectTarget[]"
      }
    },
    {
      "method": "PUT",
      "path": "/api/v1/projects/:projectId/target-users/:targetUserId/message",
      "scopes": [
        "communications"
      ],
      "category": "projects",
      "description": "Save an exact draft message for one project target by target user id. This updates the reviewable project draft and does not send it.",
      "request": {
        "delegate_user_id": "uuid (optional)",
        "message": "string",
        "message_source": "ai_generated|user_edited (optional)",
        "review_action": "save|approve (optional; use approve only after explicit approval)",
        "contact_channel": "string (optional, e.g. gmail_send or linkedin_send_message)",
        "recipient_email": "string (optional for Gmail delivery; may be a returned option or a valid user-supplied address)"
      },
      "response": {
        "success": "boolean",
        "owner_user_id": "uuid",
        "acting_user_id": "uuid",
        "project_id": "uuid",
        "target_user_id": "uuid",
        "target": "ProjectTarget"
      }
    },
    {
      "method": "PUT",
      "path": "/api/v1/projects/:projectId/targets/:targetId/message",
      "scopes": [
        "communications"
      ],
      "category": "projects",
      "description": "Save an exact draft message for one project target by assignment target row id. This updates the reviewable project draft and does not send it.",
      "request": {
        "delegate_user_id": "uuid (optional)",
        "message": "string",
        "message_source": "ai_generated|user_edited (optional)",
        "review_action": "save|approve (optional; use approve only after explicit approval)",
        "contact_channel": "string (optional)",
        "recipient_email": "string (optional for Gmail delivery; may be a returned option or a valid user-supplied address)"
      },
      "response": {
        "success": "boolean",
        "owner_user_id": "uuid",
        "acting_user_id": "uuid",
        "project_id": "uuid",
        "assignment_target_id": "uuid",
        "target": "ProjectTarget"
      }
    },
    {
      "method": "GET",
      "path": "/api/v1/projects/:projectId/send-readiness",
      "scopes": [
        "communications"
      ],
      "category": "projects",
      "description": "Read the project send-confirm readiness summary: ready target count, previewed/not-previewed/edited/stale breakdown, stale target ids, and delivery-channel buckets.",
      "request": {
        "delegate_user_id": "uuid (optional)"
      },
      "response": {
        "success": "boolean",
        "owner_user_id": "uuid",
        "acting_user_id": "uuid",
        "project_id": "uuid",
        "summary": "ProjectSendReadinessSummary"
      }
    },
    {
      "method": "POST",
      "path": "/api/v1/projects/:projectId/activate",
      "scopes": [
        "communications"
      ],
      "category": "projects",
      "description": "Start delivery for a reviewed project. Eligible included targets are marked for dispatch, the project becomes active, and channel-specific queues handle LinkedIn daily caps and automatic resume.",
      "request": {
        "delegate_user_id": "uuid (optional)"
      },
      "response": {
        "success": "boolean",
        "owner_user_id": "uuid",
        "acting_user_id": "uuid",
        "project_id": "uuid",
        "message": "string",
        "project": "Project"
      }
    },
    {
      "method": "POST",
      "path": "/api/v1/search/people/preview",
      "scopes": [
        "search"
      ],
      "category": "people-search",
      "description": "Run a preview people search (auto-translated description/query, no enrichment, not enrichable). LinkedIn lookup is not supported. include_evidence_text is optional when you need inline profile evidence on preview rows.",
      "request": {
        "description": "string",
        "query": "string (legacy alias)",
        "keywords": "string|array (deprecated)",
        "limit": "number",
        "offset": "number",
        "search_metadata": "object",
        "filters": "object (optional)",
        "include_evidence_text": "boolean (optional)",
        "evidence_text_mode": "string (optional, base|full)",
        "evidence_posts_limit": "number (optional)",
        "delegate_user_id": "uuid (optional)"
      },
      "response": {
        "success": "boolean",
        "search_id": "null",
        "users": "Person[]",
        "pagination": "object",
        "search_metadata": "object"
      }
    },
    {
      "method": "POST",
      "path": "/api/v1/search/people/enrich",
      "scopes": [
        "enrich"
      ],
      "category": "people-search",
      "description": "Re-run a full search with enrichment enabled using a search_id. Provide target_user_id to enrich one user, or omit it to enrich the current page of results. include_evidence_text can be supplied here even if the original search omitted it.",
      "request": {
        "search_id": "string",
        "limit": "number (optional)",
        "offset": "number (optional)",
        "target_user_id": "uuid (optional)",
        "include_evidence_text": "boolean (optional)",
        "evidence_text_mode": "string (optional, base|full)",
        "evidence_posts_limit": "number (optional)"
      },
      "response": {
        "success": "boolean",
        "users": "Person[]",
        "pagination": "object",
        "enrichment": "object"
      }
    },
    {
      "method": "POST",
      "path": "/api/v1/companies/search/preview",
      "scopes": [
        "search"
      ],
      "category": "companies",
      "description": "Search companies in preview or detailed mode. Natural language queries are translated into company filters; returns a company search_id for follow-on people search joins. Set result_mode=detailed to expand each row with richer company fields, and include_evidence_text=true to inline evidence text built from stored company docs/posts.",
      "request": {
        "query": "string",
        "description": "string (optional alias for query)",
        "filters": "object (optional)",
        "preview_limit": "number (optional)",
        "result_mode": "string (optional, preview|detailed)",
        "include_evidence_text": "boolean (optional)",
        "evidence_post_limit": "number (optional)",
        "delegate_user_id": "uuid (optional)"
      },
      "response": {
        "success": "boolean",
        "companies": "array",
        "pagination": "object",
        "filters": "object",
        "company_resolution": "object",
        "annotationPayload": "object"
      }
    },
    {
      "method": "POST",
      "path": "/api/v1/search/jobs/preview",
      "scopes": [
        "search"
      ],
      "category": "jobs",
      "description": "Natural-language job search scored against the viewer social-graph overlay. Accepts the full AdvancedFilters doc (hiring.*, companies.include/exclude, industries, company_stage, locations), including hiring.workplace_types for derived remote/hybrid/onsite/unknown filtering and hiring.published_within_days/published_after/published_before for hard posting-date filters. Each result row is decorated with a network block summarizing 1st/2nd-degree connections the viewer has at the posting company.",
      "request": {
        "query": "string (optional, natural-language)",
        "filters": "object (optional, AdvancedFilters; posting recency under hiring.published_*)",
        "preview_limit": "number (optional, default 10, max 25)",
        "delegate_user_id": "uuid (optional)"
      },
      "response": {
        "success": "boolean",
        "durationMs": "number",
        "total": "number",
        "preview_limit": "number",
        "delegate_user_id": "uuid|null",
        "viewer_profile": "object|null",
        "applied_filter_summary": "object",
        "network_overlay_status": "JobNetworkOverlayStatus",
        "results": "JobPosting[]",
        "search_activity_id": "uuid|null"
      }
    },
    {
      "method": "POST",
      "path": "/api/v1/search/jobs/with-people",
      "scopes": [
        "search"
      ],
      "category": "jobs",
      "description": "The 'map a job to a path in' surface. Groups job_search_preview results by company and returns an inline slice of the viewer's 1st/2nd-degree people at each company. Billed as one preview search; sub-queries are linked via parent_search_activity_id.",
      "request": {
        "query": "string (optional, natural-language)",
        "filters": "object (optional, AdvancedFilters; posting recency under hiring.published_*)",
        "preview_limit": "number (optional, default 10, max 25)",
        "people_per_company": "number (optional, default 3, max 10)",
        "delegate_user_id": "uuid (optional)"
      },
      "response": {
        "success": "boolean",
        "durationMs": "number",
        "total": "number",
        "companies_in_order": "uuid[]",
        "network_overlay_status": "JobNetworkOverlayStatus",
        "groups": "JobsWithPeopleGroup[]",
        "viewer_profile": "object|null",
        "search_activity_id": "uuid|null"
      }
    },
    {
      "method": "POST",
      "path": "/api/v1/search/posts/preview",
      "scopes": [
        "search"
      ],
      "category": "posts",
      "description": "Direct post/activity search. Supports a hard known-author cohort via filters.posts.author_user_ids (UUIDs) or author_user_id_ints (positive integers), literal mentions, expanded topic keywords, authored-account type, action types, engagement counts, date windows, and target constraints. Returned post rows use a Super Carl post id suitable for post://<id> inline references; ingestion-provider identifiers are not part of the API contract. For companies qualified by official posts, combine author_entity_types:[\"company\"] with action_types:[\"post\"] and with_companies:true; matching company actors are deduped into answer-ready companies[] rows with compact matched_posts evidence and explicit resolved/observed identity status. Without with_companies:true, the same filters remain post-primary. Returns matching post rows plus a people_search_binding for pivoting into profile search.",
      "request": {
        "query": "string (optional, text/topic query)",
        "filters": "object (optional; filters.posts supports author_user_ids/author_user_id_ints for a hard authored-post cohort, plus topic, action, account-type, date, engagement, and target fields)",
        "preview_limit": "number (optional, default 10, max 50)",
        "offset": "number (optional)",
        "sort_by": "string (optional, relevance|recent|engagement|reactions|comments)",
        "sort_order": "string (optional, asc|desc)",
        "with_companies": "boolean (optional, default false; join official company actors as the answer object)",
        "delegate_user_id": "uuid (optional)"
      },
      "response": {
        "success": "boolean",
        "durationMs": "number",
        "total": "number",
        "preview_limit": "number",
        "offset": "number",
        "has_more": "boolean",
        "applied_filter_summary": "object",
        "author_cohort_filter_status": "object|null",
        "people_search_binding": "object",
        "results": "ActivityPost[]",
        "companies": "PostMatchedCompany[] (present when with_companies=true)",
        "search_activity_id": "uuid|null"
      }
    },
    {
      "method": "POST",
      "path": "/api/v1/search/posts/with-people",
      "scopes": [
        "search"
      ],
      "category": "posts",
      "description": "Post/activity search plus a deduped people set derived from matching person actors/authors. Set with_companies:true to additionally request the same PostMatchedCompany[] cohort as preview. Use for post-first \"who\" questions, then execute people_search_binding when full profile search, relationship detail, or additional structured constraints are needed.",
      "request": {
        "query": "string (optional, text/topic query)",
        "filters": "object (optional; filters.posts supports author_user_ids/author_user_id_ints for a hard authored-post cohort, plus topic, action, account-type, date, engagement, and target fields)",
        "preview_limit": "number (optional, default 10, max 50)",
        "offset": "number (optional)",
        "people_limit": "number (optional, default 25, max 100)",
        "sort_by": "string (optional, relevance|recent|engagement|reactions|comments)",
        "sort_order": "string (optional, asc|desc)",
        "with_companies": "boolean (optional, default false; join official company actors as the answer object)",
        "delegate_user_id": "uuid (optional)"
      },
      "response": {
        "success": "boolean",
        "durationMs": "number",
        "total": "number",
        "results": "ActivityPost[]",
        "people": "PostMatchedPerson[]",
        "companies": "PostMatchedCompany[] (present when with_companies=true)",
        "author_cohort_filter_status": "object|null",
        "people_search_binding": "object",
        "search_activity_id": "uuid|null"
      }
    },
    {
      "method": "GET",
      "path": "/api/v1/profiles/:id/chunks",
      "scopes": [
        "profiles-read"
      ],
      "category": "profiles",
      "description": "Fetch cached profile chunks (no refresh).",
      "request": {
        "posts_limit": "number (optional)"
      },
      "response": {
        "success": "boolean",
        "user_id": "uuid",
        "chunks": "ProfileChunk[]"
      }
    },
    {
      "method": "GET",
      "path": "/api/v1/profiles/:id/text",
      "scopes": [
        "profiles-read"
      ],
      "category": "profiles",
      "description": "Fetch profile text ready for LLM embeddings or contextual matching.",
      "request": {
        "mode": "string (optional, base|full; base=embedding input, full=adds posts + company signals)",
        "posts_limit": "number (optional)"
      },
      "response": {
        "success": "boolean",
        "user_id": "uuid",
        "text": "ProfileText"
      }
    },
    {
      "method": "GET",
      "path": "/api/v1/profiles/:id",
      "scopes": [
        "profiles-read"
      ],
      "category": "profiles",
      "description": "Fetch a profile snapshot by user id.",
      "response": {
        "id": "uuid",
        "name": "string",
        "username": "string|null",
        "picture": "string|null",
        "bio": "string|null",
        "location": "string|null",
        "linkedin_url": "string|null",
        "supercarl_url": "string|null",
        "created_at": "string",
        "last_active": "string|null"
      }
    }
  ]
}
