{
  "openapi": "3.1.0",
  "info": {
    "title": "The Workflow Finder Search API",
    "version": "1.0.0",
    "summary": "Key-less search over a hand-curated catalog of AI tools and step-by-step workflows.",
    "description": "One GET endpoint over the same in-memory catalog every page on theworkflowfinder.com renders from. No API key, no signup. Responses follow public score contract 1.0: review (product-quality Review Score, nullable), fitScores (use-case fit, not quality), externalRating (attributed third-party reference or null) and legacyRating (deprecated compatibility values). The search score is query relevance only. The same catalog is reachable over MCP at POST /api/mcp; see https://www.theworkflowfinder.com/mcp-docs.",
    "termsOfService": "https://www.theworkflowfinder.com/terms",
    "contact": {
      "name": "The Workflow Finder",
      "url": "https://www.theworkflowfinder.com/contact"
    }
  },
  "externalDocs": {
    "description": "Human-readable API documentation",
    "url": "https://www.theworkflowfinder.com/api-docs"
  },
  "servers": [
    {
      "url": "https://www.theworkflowfinder.com"
    }
  ],
  "tags": [
    {
      "name": "search",
      "description": "Catalog search"
    }
  ],
  "paths": {
    "/api/v1/search": {
      "get": {
        "tags": [
          "search"
        ],
        "operationId": "searchCatalog",
        "summary": "Search tools and workflows",
        "description": "All parameters are optional. An empty query returns the catalog subject to the result limit. Tools are ranked by query relevance; ties and empty queries use eligible product-quality reviews, then curated featured status and alphabetical name. Legacy ratings and review counts are never ranking inputs. Filters that resolve against optional tool data (budget, capabilities, openSource, apiAvailability) exclude a tool when the data is absent rather than assuming it passes.",
        "parameters": [
          {
            "name": "task",
            "in": "query",
            "description": "Free-text description of what you are trying to do. Tokenized and matched against tool and workflow text.",
            "schema": {
              "type": "string",
              "maxLength": 500
            }
          },
          {
            "name": "category",
            "in": "query",
            "description": "One of the 13 tool categories, for example Coding, Marketing, Design. Matches a workflow when it appears among the workflow tags.",
            "schema": {
              "type": "string",
              "maxLength": 50
            }
          },
          {
            "name": "pricing",
            "in": "query",
            "description": "Pricing bucket.",
            "schema": {
              "type": "string",
              "enum": [
                "free",
                "freemium",
                "paid"
              ]
            }
          },
          {
            "name": "budget",
            "in": "query",
            "description": "Maximum monthly price. Excludes tools whose parseable leading price is above it; tools with unparseable pricing (quote-based) pass through.",
            "schema": {
              "type": "number",
              "exclusiveMinimum": 0
            }
          },
          {
            "name": "needs",
            "in": "query",
            "description": "Comma-separated extra keywords, combined with task.",
            "schema": {
              "type": "string",
              "maxLength": 500
            }
          },
          {
            "name": "avoid",
            "in": "query",
            "description": "Comma-separated keywords that exclude a result if found anywhere in its text.",
            "schema": {
              "type": "string",
              "maxLength": 500
            }
          },
          {
            "name": "capabilities",
            "in": "query",
            "description": "Comma-separated capability tags. A tool matches when it carries at least one of them. Every value must be one of the 29 tags listed in components.schemas.CapabilityTag.",
            "schema": {
              "type": "string",
              "maxLength": 500
            },
            "example": "Code generation,Code review"
          },
          {
            "name": "openSource",
            "in": "query",
            "description": "Filter on the recorded open-source status in the tool facts.",
            "schema": {
              "type": "string",
              "enum": [
                "true",
                "false"
              ]
            }
          },
          {
            "name": "apiAvailability",
            "in": "query",
            "description": "Filter on the recorded API availability in the tool facts.",
            "schema": {
              "type": "string",
              "enum": [
                "public",
                "waitlist",
                "none",
                "not-published"
              ]
            }
          },
          {
            "name": "type",
            "in": "query",
            "description": "Which content type to search. Defaults to both.",
            "schema": {
              "type": "string",
              "enum": [
                "tools",
                "workflows",
                "both"
              ],
              "default": "both"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "description": "Maximum results per content type.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 50,
              "default": 10
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Ranked matches for each requested content type.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SearchResult"
                },
                "examples": {
                  "taskSearch": {
                    "summary": "GET /api/v1/search?task=automate+social+media+posts&limit=1",
                    "description": "Verbatim production response captured 2026-09-12.",
                    "value": {
                      "query": {
                        "task": "automate social media posts",
                        "limit": 1
                      },
                      "tools": [
                        {
                          "slug": "sprout-social",
                          "name": "Sprout Social",
                          "url": "https://www.theworkflowfinder.com/tools/sprout-social",
                          "category": "Marketing",
                          "pricing": "paid",
                          "pricingDetail": "$199/seat/mo Standard / $299/seat/mo Professional / $399/seat/mo Advanced (30-day trial, no free tier)",
                          "shortDescription": "Run publishing, sentiment-aware inbox triage, and competitor listening for a whole social team from one enterprise dashboard.",
                          "rating": 4.4,
                          "reviewCount": 4300,
                          "review": {
                            "status": "not-reviewed",
                            "qualityScore": null,
                            "limitedScore": null,
                            "scale": 5,
                            "scope": null,
                            "testedAt": null,
                            "publishedAt": null,
                            "reviewUrl": null,
                            "reason": "No published, evidence-backed product-quality review yet.",
                            "methodologyUrl": "/review-methodology"
                          },
                          "fitScores": [
                            {
                              "useCase": "Larger marketing and social teams needing a unified inbox with sentiment-aware prioritization for high message volume",
                              "capability": 5,
                              "reliability": 4,
                              "value": 3,
                              "ease": 3,
                              "compatibility": 4,
                              "overall": 3.8,
                              "rationale": "Directly the tool's bestFor and standout: the Smart Inbox routes every comment and DM into one queue with sentiment analysis flagging priority, matching pros on enterprise-grade reporting and cutting through high message volume."
                            },
                            {
                              "useCase": "A small company or solo social media manager mainly scheduling posts",
                              "capability": 2,
                              "reliability": 3,
                              "value": 1,
                              "ease": 2,
                              "compatibility": 2,
                              "overall": 2,
                              "rationale": "The tool's own ourTake and con state the per-seat pricing with no free tier is impossible to justify for smaller companies relative to lighter alternatives, and the full feature set requires the top Advanced plan."
                            }
                          ],
                          "externalRating": null,
                          "legacyRating": {
                            "value": 4.4,
                            "reviewCount": 4300,
                            "provenance": "unverified",
                            "deprecated": true,
                            "notice": "Legacy rating/reviewCount fields are not TWF Review Scores or verified on-site review totals."
                          },
                          "bestFor": "Larger marketing and social teams that need a unified inbox with sentiment-aware prioritization, not just scheduling",
                          "ourTake": "Sprout Social is enterprise social media management, and per-seat pricing at $199 to $399 per month with no free tier signals who it's built for. The Smart Inbox routes every comment, mention, and DM into one queue and uses sentiment analysis to flag which messages need a human response first, a real operational advantage for teams handling high message volume. Smaller companies and solo social managers will find the price impossible to justify relative to lighter alternatives. The full feature set requires the top Advanced plan. Evaluate it when you're managing a large team with real message volume, not when scheduling posts is the main job.",
                          "capabilities": [
                            "Social media content",
                            "Ad campaign management"
                          ],
                          "facts": {
                            "privacyPolicyUrl": "https://sproutsocial.com/legal/privacy-policy/",
                            "trustPageUrl": "https://sproutsocial.com/trust-center/",
                            "openSource": false,
                            "apiAvailability": "public",
                            "pricingVerifiedAt": "2026-08"
                          },
                          "score": 4,
                          "matchedOn": [
                            "4 keyword matches"
                          ]
                        }
                      ],
                      "workflows": [
                        {
                          "slug": "automate-social-media-posts",
                          "title": "Automate Social Media Posts",
                          "url": "https://www.theworkflowfinder.com/workflows/automate-social-media-posts",
                          "difficulty": "Intermediate",
                          "timeEstimate": "1 hr setup / 5 min weekly",
                          "description": "Learn how to automatically generate and schedule social media posts from your blog articles using AI and automation tools.",
                          "expectedResult": "A fully automated pipeline that drafts and schedules tweets and LinkedIn posts every time you publish a new blog post.",
                          "tags": [
                            "Social Media",
                            "Automation",
                            "Marketing"
                          ],
                          "score": 4,
                          "matchedOn": [
                            "4 keyword matches"
                          ]
                        }
                      ],
                      "meta": {
                        "totalToolMatches": 130,
                        "totalWorkflowMatches": 96,
                        "source": "https://www.theworkflowfinder.com",
                        "generated": "2026-08-28",
                        "scoreContractVersion": "1.0",
                        "scoring": {
                          "methodologyUrl": "https://www.theworkflowfinder.com/review-methodology",
                          "review": {
                            "statuses": [
                              "not-reviewed",
                              "limited",
                              "reviewed",
                              "needs-update",
                              "blocked"
                            ],
                            "scale": 5,
                            "qualityScore": "Product-quality Review Score only when status is reviewed; otherwise null, never zero.",
                            "limitedScore": "A narrower published editorial rating, not a product-quality Review Score or a quality-ranking input.",
                            "nullMeaning": "No publishable product-quality score; not a negative quality judgment. See status, reason and scope."
                          },
                          "fitScores": {
                            "methodologyUrl": "https://www.theworkflowfinder.com/fit-score",
                            "scale": 5,
                            "meaning": "Existing use-case-specific editorial Fit Scores, not product-quality Review Scores or measured benchmarks. An empty array means no Fit Scores are recorded."
                          },
                          "externalRating": "Attributed third-party reference with publisher, sourceUrl and checkedAt; null when no verified reference is available. Not a TWF Review Score.",
                          "legacyRating": {
                            "deprecatedFields": [
                              "rating",
                              "reviewCount"
                            ],
                            "notice": "Legacy numeric fields are preserved unchanged where exposed. Use legacyRating for their provenance and deprecation notice; they are not TWF Review Scores or verified on-site review totals."
                          },
                          "searchScore": "score is query relevance, not a Review Score or a use-case Fit Score.",
                          "ranking": "Query relevance first; ties and empty queries use eligible product-quality reviews, then curated featured status and alphabetical name/slug. Unreviewed and limited tools have no numeric quality rank; legacy ratings and review counts are never ranking inputs."
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "A malformed or out-of-range parameter. The body names the specific issue.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ValidationError"
                },
                "examples": {
                  "invalidPricing": {
                    "summary": "GET /api/v1/search?pricing=expensive",
                    "description": "Verbatim production response captured 2026-09-12.",
                    "value": {
                      "error": "Invalid query parameters",
                      "details": [
                        {
                          "received": "expensive",
                          "code": "invalid_enum_value",
                          "options": [
                            "free",
                            "freemium",
                            "paid"
                          ],
                          "path": [
                            "pricing"
                          ],
                          "message": "Invalid enum value. Expected 'free' | 'freemium' | 'paid', received 'expensive'"
                        }
                      ]
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Per-IP rate limit exceeded. Wait for the number of seconds in Retry-After before retrying.",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying.",
                "schema": {
                  "type": "string"
                },
                "example": "60"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  }
                },
                "example": {
                  "error": "Too many search requests. Please try again later."
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "CapabilityTag": {
        "type": "string",
        "enum": [
          "Web research",
          "Source synthesis",
          "Data analysis",
          "Competitive analysis",
          "Long-form writing",
          "Script generation",
          "Image generation",
          "Video generation",
          "Audio & voice generation",
          "Social media content",
          "Code generation",
          "Code review",
          "Debugging assistance",
          "API integration",
          "Lead generation",
          "CRM automation",
          "Outreach & email sequencing",
          "Sales call analysis",
          "Workflow automation",
          "Scheduling & calendar management",
          "Document processing",
          "Customer support automation",
          "SEO optimization",
          "Ad campaign management",
          "Email marketing",
          "Multi-step agent orchestration",
          "Autonomous task execution",
          "Meeting transcription & summarization",
          "Note-taking & knowledge management"
        ]
      },
      "SearchResult": {
        "type": "object",
        "required": [
          "query",
          "tools",
          "workflows",
          "meta"
        ],
        "properties": {
          "query": {
            "type": "object",
            "description": "The parsed query the server actually ran.",
            "additionalProperties": true
          },
          "tools": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ToolSearchResult"
            }
          },
          "workflows": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WorkflowSearchResult"
            }
          },
          "meta": {
            "$ref": "#/components/schemas/SearchMeta"
          }
        }
      },
      "SearchMeta": {
        "type": "object",
        "required": [
          "totalToolMatches",
          "totalWorkflowMatches",
          "source",
          "generated",
          "scoreContractVersion",
          "scoring"
        ],
        "properties": {
          "totalToolMatches": {
            "type": "integer",
            "description": "Matches before the limit was applied."
          },
          "totalWorkflowMatches": {
            "type": "integer"
          },
          "source": {
            "type": "string",
            "format": "uri"
          },
          "generated": {
            "type": "string",
            "description": "Catalog update date (YYYY-MM-DD)."
          },
          "scoreContractVersion": {
            "type": "string",
            "const": "1.0"
          },
          "scoring": {
            "type": "object",
            "description": "The public scoring contract: how to read review, fitScores, externalRating, legacyRating and score.",
            "additionalProperties": true
          }
        }
      },
      "ToolSearchResult": {
        "type": "object",
        "description": "One tool. rating and reviewCount are deprecated compatibility fields; read review, fitScores and externalRating instead.",
        "required": [
          "slug",
          "name",
          "url",
          "category",
          "pricing",
          "pricingDetail",
          "shortDescription",
          "rating",
          "reviewCount",
          "review",
          "fitScores",
          "externalRating",
          "legacyRating",
          "score",
          "matchedOn"
        ],
        "properties": {
          "slug": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "url": {
            "type": "string",
            "format": "uri",
            "description": "Canonical tool page."
          },
          "category": {
            "type": "string"
          },
          "pricing": {
            "type": "string",
            "enum": [
              "free",
              "freemium",
              "paid"
            ]
          },
          "pricingDetail": {
            "type": "string"
          },
          "shortDescription": {
            "type": "string"
          },
          "rating": {
            "type": "number",
            "deprecated": true,
            "description": "Legacy value, not a Review Score."
          },
          "reviewCount": {
            "type": "integer",
            "deprecated": true,
            "description": "Legacy value, not a verified on-site review total."
          },
          "review": {
            "$ref": "#/components/schemas/ReviewScoring"
          },
          "fitScores": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/FitScore"
            }
          },
          "externalRating": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/ExternalRating"
              },
              {
                "type": "null"
              }
            ]
          },
          "legacyRating": {
            "$ref": "#/components/schemas/LegacyRating"
          },
          "bestFor": {
            "type": "string"
          },
          "ourTake": {
            "type": "string"
          },
          "capabilities": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CapabilityTag"
            }
          },
          "facts": {
            "$ref": "#/components/schemas/ToolFacts"
          },
          "score": {
            "type": "number",
            "description": "Query relevance only. Not a Review Score or a Fit Score."
          },
          "matchedOn": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        },
        "additionalProperties": true
      },
      "WorkflowSearchResult": {
        "type": "object",
        "required": [
          "slug",
          "title",
          "url",
          "difficulty",
          "timeEstimate",
          "description",
          "expectedResult",
          "tags",
          "score",
          "matchedOn"
        ],
        "properties": {
          "slug": {
            "type": "string"
          },
          "title": {
            "type": "string"
          },
          "url": {
            "type": "string",
            "format": "uri"
          },
          "difficulty": {
            "type": "string",
            "enum": [
              "Beginner",
              "Intermediate",
              "Advanced"
            ]
          },
          "timeEstimate": {
            "type": "string"
          },
          "description": {
            "type": "string"
          },
          "expectedResult": {
            "type": "string"
          },
          "tags": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "score": {
            "type": "number",
            "description": "Query relevance only."
          },
          "matchedOn": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        }
      },
      "ReviewScoring": {
        "type": "object",
        "description": "Product-quality review contract. qualityScore is present only when status is reviewed; null is never a negative judgment.",
        "required": [
          "status",
          "qualityScore",
          "limitedScore"
        ],
        "properties": {
          "status": {
            "type": "string",
            "enum": [
              "not-reviewed",
              "limited",
              "reviewed",
              "needs-update",
              "blocked"
            ]
          },
          "qualityScore": {
            "type": [
              "number",
              "null"
            ],
            "description": "Whole-number 1 to 5 when status is reviewed, otherwise null."
          },
          "limitedScore": {
            "type": [
              "number",
              "null"
            ],
            "description": "Narrower published editorial rating, 1 to 5, only for the published scope; not a quality-ranking input."
          },
          "reason": {
            "type": [
              "string",
              "null"
            ]
          },
          "scope": {
            "type": [
              "string",
              "null"
            ]
          },
          "testedAt": {
            "type": [
              "string",
              "null"
            ]
          },
          "publishedAt": {
            "type": [
              "string",
              "null"
            ]
          },
          "reviewUrl": {
            "type": [
              "string",
              "null"
            ],
            "format": "uri"
          }
        },
        "additionalProperties": true
      },
      "FitScore": {
        "type": "object",
        "description": "Use-case-specific editorial fit, five axes scored 1 to 5 with a plain average. Not a quality review or a measured benchmark.",
        "required": [
          "useCase",
          "capability",
          "reliability",
          "value",
          "ease",
          "compatibility",
          "overall",
          "rationale"
        ],
        "properties": {
          "useCase": {
            "type": "string"
          },
          "capability": {
            "type": "integer",
            "minimum": 1,
            "maximum": 5
          },
          "reliability": {
            "type": "integer",
            "minimum": 1,
            "maximum": 5
          },
          "value": {
            "type": "integer",
            "minimum": 1,
            "maximum": 5
          },
          "ease": {
            "type": "integer",
            "minimum": 1,
            "maximum": 5
          },
          "compatibility": {
            "type": "integer",
            "minimum": 1,
            "maximum": 5
          },
          "overall": {
            "type": "number"
          },
          "rationale": {
            "type": "string"
          }
        }
      },
      "ExternalRating": {
        "type": "object",
        "description": "An attributed third-party reference. Not a TWF Review Score.",
        "properties": {
          "publisher": {
            "type": "string"
          },
          "rating": {
            "type": "number"
          },
          "reviewCount": {
            "type": "integer"
          },
          "sourceUrl": {
            "type": "string",
            "format": "uri"
          },
          "checkedAt": {
            "type": "string"
          }
        },
        "additionalProperties": true
      },
      "LegacyRating": {
        "type": "object",
        "description": "Provenance and deprecation notice for the legacy rating and reviewCount fields.",
        "properties": {
          "value": {
            "type": [
              "number",
              "null"
            ]
          },
          "reviewCount": {
            "type": [
              "integer",
              "null"
            ]
          },
          "provenance": {
            "type": "string",
            "enum": [
              "unverified",
              "attributed-external-reference"
            ]
          },
          "deprecated": {
            "type": "boolean",
            "const": true
          },
          "notice": {
            "type": "string"
          }
        },
        "additionalProperties": true
      },
      "ToolFacts": {
        "type": "object",
        "description": "Source-linked facts: URLs, booleans and dates only, never scores or certifications.",
        "properties": {
          "privacyPolicyUrl": {
            "type": "string",
            "format": "uri"
          },
          "trustPageUrl": {
            "type": "string",
            "format": "uri"
          },
          "openSource": {
            "type": "boolean"
          },
          "apiAvailability": {
            "type": "string",
            "enum": [
              "public",
              "waitlist",
              "none",
              "not-published"
            ]
          },
          "pricingVerifiedAt": {
            "type": "string"
          }
        },
        "additionalProperties": true
      },
      "ValidationError": {
        "type": "object",
        "required": [
          "error",
          "details"
        ],
        "properties": {
          "error": {
            "type": "string",
            "const": "Invalid query parameters"
          },
          "details": {
            "type": "array",
            "description": "Zod issue objects naming the offending parameter.",
            "items": {
              "type": "object",
              "additionalProperties": true
            }
          }
        }
      }
    }
  }
}
