{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://stackswap.ai/schema/gtm-decision-schema.json",
  "title": "StackSwap GTM Decision Schema",
  "description": "Vendor fact-sheet schema for B2B GTM tools. Vendors and operators can submit structured facts about a tool that an agent or buyer can rely on when making a stack decision. Submitted facts are tagged with provenance and a verification date. StackSwap consumes this schema into its tool fact corpus (see https://stackswap.ai/methodology#tool-fact-corpus). Required fields are the minimum we need to publish a fact-sheet stub; optional fields enrich agent reasoning and break ties between equivalent-fit tools.",
  "type": "object",
  "version": "1.0.0",
  "required": [
    "tool_name",
    "homepage_url",
    "category",
    "verification"
  ],
  "properties": {
    "tool_name": {
      "type": "string",
      "minLength": 1,
      "description": "Canonical tool name as buyers refer to it. Must match the entry in StackSwap's TOOL_LIST (data/tools.json) if the tool already exists in the corpus."
    },
    "vendor_legal_name": {
      "type": "string",
      "description": "Legal entity that owns the tool (useful when parent company differs from product name — e.g., Salesforce Inc. owns Slack)."
    },
    "homepage_url": {
      "type": "string",
      "format": "uri",
      "description": "Canonical product homepage. Used as the primary verification anchor."
    },
    "category": {
      "type": "string",
      "description": "Primary GTM category. Examples: 'CRM', 'sales engagement', 'sales intelligence', 'marketing automation', 'customer success', 'revenue intelligence', 'meeting scheduler', 'enrichment', 'inbox warmup', 'AI SDR'."
    },
    "subcategories": {
      "type": "array",
      "items": {
        "type": "string"
      },
      "description": "Secondary categories this tool reasonably competes in. Used by the recommendation engine to detect overlap with adjacent tools."
    },
    "short_description": {
      "type": "string",
      "maxLength": 280,
      "description": "One-sentence buyer-language description. What does this tool do, for whom? Avoid marketing fluff — agents penalize it."
    },
    "pricing": {
      "type": "object",
      "description": "Pricing facts. Required if the tool has any published pricing. Use 'is_public_pricing: false' to declare 'contact sales' pricing.",
      "properties": {
        "is_public_pricing": {
          "type": "boolean",
          "description": "True if pricing is published on the vendor's site. False for 'contact sales' / custom-quote models."
        },
        "pricing_model": {
          "type": "string",
          "enum": [
            "per_seat",
            "usage_based",
            "flat_monthly",
            "tiered",
            "freemium",
            "custom_quote",
            "hybrid"
          ],
          "description": "Primary pricing model. Use 'hybrid' when pricing combines two models (e.g., per-seat base + usage overage)."
        },
        "currency": {
          "type": "string",
          "enum": ["USD", "EUR", "GBP", "AUD", "CAD"],
          "default": "USD",
          "description": "Currency for all numeric pricing fields."
        },
        "starting_monthly_price_usd": {
          "type": "number",
          "minimum": 0,
          "description": "Lowest entry price in USD/month for a single seat or the smallest viable purchase. Free tiers should set this to 0 and use 'has_free_tier: true'."
        },
        "has_free_tier": {
          "type": "boolean",
          "description": "True if a permanently-free tier exists (not just a trial)."
        },
        "trial_days": {
          "type": "integer",
          "minimum": 0,
          "description": "Length of free trial in days. 0 if no trial."
        },
        "tiers": {
          "type": "array",
          "description": "Named pricing tiers if the tool publishes them. Use this to disclose gotchas — feature gates, seat minimums, annual-only pricing.",
          "items": {
            "type": "object",
            "required": ["name", "price_usd_monthly_per_seat"],
            "properties": {
              "name": { "type": "string" },
              "price_usd_monthly_per_seat": { "type": "number", "minimum": 0 },
              "billed_annually_only": { "type": "boolean" },
              "min_seats": { "type": "integer", "minimum": 1 },
              "included_usage": {
                "type": "string",
                "description": "What the tier includes in plain language. E.g., '500 enrichment credits/mo', '5GB storage', '10 active workflows'."
              },
              "gotchas": {
                "type": "array",
                "items": { "type": "string" },
                "description": "Honest list of feature gates, contract minimums, overage fees, or surprise costs at this tier. Vendor self-disclosure of gotchas earns trust signal in the recommendation engine."
              }
            }
          }
        },
        "contract_minimum_months": {
          "type": "integer",
          "minimum": 0,
          "description": "Minimum contract term in months. 0 = month-to-month available."
        },
        "contract_minimum_seats": {
          "type": "integer",
          "minimum": 1,
          "description": "Minimum seat count for the lowest-priced tier. Important for SMB buyers."
        },
        "published_pricing_url": {
          "type": "string",
          "format": "uri",
          "description": "Canonical URL where pricing is published. Used for automated re-verification."
        },
        "negotiation_signals": {
          "type": "object",
          "description": "Optional. What buyers actually achieve when negotiating. Vendor-submitted values are treated as 'list price' anchors; user-reported negotiation outcomes can override these in StackSwap's fact corpus.",
          "properties": {
            "typical_discount_percent_annual_commit": { "type": "number", "minimum": 0, "maximum": 100 },
            "typical_discount_percent_multi_year": { "type": "number", "minimum": 0, "maximum": 100 },
            "end_of_quarter_flexibility": { "type": "boolean" }
          }
        }
      }
    },
    "integrations": {
      "type": "object",
      "description": "Integration surface. Used by the recommendation engine to score stack compatibility.",
      "properties": {
        "native_integrations": {
          "type": "array",
          "description": "First-party integrations the vendor builds and maintains. Distinct from Zapier/Make-only connectivity.",
          "items": {
            "type": "object",
            "required": ["target_tool"],
            "properties": {
              "target_tool": {
                "type": "string",
                "description": "Name of the integrated tool. Should match a TOOL_LIST entry when applicable."
              },
              "integration_type": {
                "type": "string",
                "enum": ["bidirectional_sync", "one_way_push", "one_way_pull", "webhook_only", "embed", "sso_only"]
              },
              "depth_score": {
                "type": "integer",
                "minimum": 1,
                "maximum": 5,
                "description": "1 = SSO only or trivial pass-through. 3 = standard CRUD sync. 5 = deep bidirectional with custom-object support and conflict resolution."
              },
              "docs_url": { "type": "string", "format": "uri" }
            }
          }
        },
        "api_available": { "type": "boolean", "description": "Public REST or GraphQL API available." },
        "api_docs_url": { "type": "string", "format": "uri" },
        "webhooks_available": { "type": "boolean" },
        "mcp_server_available": {
          "type": "boolean",
          "description": "Native MCP (Model Context Protocol) server exposed for agent consumption. Material signal for agent-era buyers."
        },
        "mcp_server_url": { "type": "string", "format": "uri" },
        "zapier_app": { "type": "boolean" },
        "make_app": { "type": "boolean" },
        "n8n_node": { "type": "boolean" }
      }
    },
    "data_coverage": {
      "type": "object",
      "description": "Only relevant for data products (sales intelligence, enrichment, intent, ABM). Omit for non-data tools.",
      "properties": {
        "contact_database_size": {
          "type": "integer",
          "description": "Total contact records in the database. Vendor-attested; periodically cross-checked against third-party benchmarks."
        },
        "company_database_size": { "type": "integer" },
        "regions_covered": {
          "type": "array",
          "items": {
            "type": "string",
            "enum": ["NAM", "EMEA", "APAC", "LATAM", "ANZ", "MEA"]
          }
        },
        "data_freshness_sla_days": {
          "type": "integer",
          "minimum": 1,
          "description": "Vendor's stated maximum age of a contact record before it's refreshed or flagged stale."
        },
        "compliance_certifications": {
          "type": "array",
          "items": {
            "type": "string",
            "enum": ["SOC2_TYPE_1", "SOC2_TYPE_2", "ISO27001", "GDPR", "CCPA", "HIPAA", "FedRAMP_LI_SaaS", "FedRAMP_Moderate", "FedRAMP_High"]
          }
        }
      }
    },
    "ai_capabilities": {
      "type": "object",
      "description": "AI / LLM features the product exposes. Material for buyers evaluating AI-readiness of their stack.",
      "properties": {
        "has_native_ai_features": { "type": "boolean" },
        "ai_feature_summary": {
          "type": "string",
          "description": "Plain-language summary of what AI does in the product. Avoid 'AI-powered' marketing language — describe the actual user-facing capability."
        },
        "llm_providers_used": {
          "type": "array",
          "items": {
            "type": "string",
            "enum": ["anthropic", "openai", "google", "meta_llama", "mistral", "cohere", "in_house", "other", "undisclosed"]
          }
        },
        "customer_data_used_for_training": {
          "type": "string",
          "enum": ["never", "opt_in_only", "opt_out_only", "always", "undisclosed"],
          "description": "Whether customer data is used to train vendor or third-party models. 'opt_in_only' and 'never' are buyer trust signals."
        },
        "agent_consumable": {
          "type": "boolean",
          "description": "True if the product exposes its functionality to AI agents (MCP, function-calling API, structured outputs). Increasingly material for buyer decisions."
        }
      }
    },
    "affiliate_program": {
      "type": "object",
      "description": "Affiliate / partner program details. Disclosing this honestly affects how StackSwap labels links to your tool, NOT whether or where it ranks (see https://stackswap.ai/methodology#editorial-firewall).",
      "properties": {
        "has_affiliate_program": { "type": "boolean" },
        "program_url": { "type": "string", "format": "uri" },
        "commission_structure": {
          "type": "string",
          "description": "Plain-language description. E.g., '20% recurring for 12 months', '$200 flat per qualified sign-up'."
        },
        "cookie_window_days": { "type": "integer", "minimum": 0 }
      }
    },
    "carveout_disclosures": {
      "type": "object",
      "description": "Self-disclosed practices that may affect editorial coverage. See https://stackswap.ai/methodology#carveouts for the full carveout policy.",
      "properties": {
        "uses_exit_intent_popups": { "type": "boolean" },
        "uses_drip_sequences_without_explicit_optin": { "type": "boolean" },
        "core_motion_is_cold_email_at_scale": { "type": "boolean" },
        "incentivizes_reviews_with_compensation": { "type": "boolean" }
      }
    },
    "verification": {
      "type": "object",
      "required": ["submitted_by", "last_verified_at"],
      "description": "Provenance and freshness. Required on every submission. StackSwap surfaces these stamps on every published fact-sheet so buyers and agents can judge trust.",
      "properties": {
        "submitted_by": {
          "type": "string",
          "enum": ["vendor", "stackswap", "third_party"],
          "description": "Who supplied this fact sheet. 'vendor' = official submission from the tool's vendor. 'stackswap' = StackSwap-curated from public sources. 'third_party' = community-submitted (e.g., an operator who uses the tool)."
        },
        "vendor_contact_email": {
          "type": "string",
          "format": "email",
          "description": "Contact at the vendor for clarifying questions. Required if submitted_by = 'vendor'."
        },
        "last_verified_at": {
          "type": "string",
          "format": "date",
          "description": "ISO 8601 date (YYYY-MM-DD) the facts were last verified accurate. StackSwap re-verifies pricing every 30-90 days; vendors are invited to resubmit when facts change."
        },
        "attestation": {
          "type": "string",
          "description": "If submitted_by = 'vendor', a one-line attestation: 'I am authorized to submit this fact sheet on behalf of [vendor] and attest these facts are accurate as of [date].' StackSwap stores attestations as part of the editorial record."
        },
        "conflicts_acknowledged": {
          "type": "array",
          "description": "Known disagreements between this fact sheet and publicly-reported buyer experience (Reddit, support tickets, G2 reviews). Self-disclosing conflicts here pre-empts the 'surface both' policy and earns trust.",
          "items": {
            "type": "object",
            "required": ["field", "vendor_position", "user_reported_position"],
            "properties": {
              "field": { "type": "string", "description": "JSON pointer or dotted path to the disputed field, e.g., 'pricing.starting_monthly_price_usd'." },
              "vendor_position": { "type": "string" },
              "user_reported_position": { "type": "string" },
              "vendor_response": { "type": "string", "description": "Optional. The vendor's response to the user-reported gap — e.g., 'effective Q3 2026 our published price increased; users on legacy contracts retain prior pricing'." }
            }
          }
        }
      }
    }
  },
  "$comment": "Submission process: email a populated JSON document to nick@stackswap.ai. Vendor-submitted fact sheets are reviewed against public sources within 7 business days. Discrepancies trigger a clarification request; honest self-disclosure of conflicts (via `verification.conflicts_acknowledged`) accelerates publication. Resubmit whenever material facts change (new pricing, new tier, acquisition, product retirement). Version 1.0.0 of this schema is stable; backward-compatible additions are versioned 1.x.0 and announced in https://stackswap.ai/methodology/changelog. Breaking changes bump to 2.0.0 with a 90-day deprecation window for existing submissions."
}
