{
  "schemaVersion": "1.0",
  "item": {
    "slug": "smb-sales-boost-leads",
    "name": "SMB Sales Boost — B2B Lead Database of SMBs for Cold Outreach & GTM",
    "source": "tencent",
    "type": "skill",
    "category": "开发工具",
    "sourceUrl": "https://clawhub.ai/Tomsonx232/smb-sales-boost-leads",
    "canonicalUrl": "https://clawhub.ai/Tomsonx232/smb-sales-boost-leads",
    "targetPlatform": "OpenClaw"
  },
  "install": {
    "downloadMode": "redirect",
    "downloadUrl": "/downloads/smb-sales-boost-leads",
    "sourceDownloadUrl": "https://wry-manatee-359.convex.site/api/v1/download?slug=smb-sales-boost-leads",
    "sourcePlatform": "tencent",
    "targetPlatform": "OpenClaw",
    "installMethod": "Manual import",
    "extraction": "Extract archive",
    "prerequisites": [
      "OpenClaw"
    ],
    "packageFormat": "ZIP package",
    "includedAssets": [
      "README.md",
      "SKILL.md",
      "openapi.json",
      "smb_api.py"
    ],
    "primaryDoc": "SKILL.md",
    "quickSetup": [
      "Download the package from Yavira.",
      "Extract the archive and review SKILL.md first.",
      "Import or place the package into your OpenClaw setup."
    ],
    "agentAssist": {
      "summary": "Hand the extracted package to your coding agent with a concrete install brief instead of figuring it out manually.",
      "steps": [
        "Download the package from Yavira.",
        "Extract it into a folder your agent can access.",
        "Paste one of the prompts below and point your agent at the extracted folder."
      ],
      "prompts": [
        {
          "label": "New install",
          "body": "I downloaded a skill package from Yavira. Read SKILL.md from the extracted folder and install it by following the included instructions. Then review README.md for any prerequisites, environment setup, or post-install checks. Tell me what you changed and call out any manual steps you could not complete."
        },
        {
          "label": "Upgrade existing",
          "body": "I downloaded an updated skill package from Yavira. Read SKILL.md from the extracted folder, compare it with my current installation, and upgrade it while preserving any custom configuration unless the package docs explicitly say otherwise. Then review README.md for any prerequisites, environment setup, or post-install checks. Summarize what changed and any follow-up checks I should run."
        }
      ]
    },
    "sourceHealth": {
      "source": "tencent",
      "status": "healthy",
      "reason": "direct_download_ok",
      "recommendedAction": "download",
      "checkedAt": "2026-05-07T17:22:31.273Z",
      "expiresAt": "2026-05-14T17:22:31.273Z",
      "httpStatus": 200,
      "finalUrl": "https://wry-manatee-359.convex.site/api/v1/download?slug=afrexai-annual-report",
      "contentType": "application/zip",
      "probeMethod": "head",
      "details": {
        "probeUrl": "https://wry-manatee-359.convex.site/api/v1/download?slug=afrexai-annual-report",
        "contentDisposition": "attachment; filename=\"afrexai-annual-report-1.0.0.zip\"",
        "redirectLocation": null,
        "bodySnippet": null
      },
      "scope": "source",
      "summary": "Source download looks usable.",
      "detail": "Yavira can redirect you to the upstream package for this source.",
      "primaryActionLabel": "Download for OpenClaw",
      "primaryActionHref": "/downloads/smb-sales-boost-leads"
    },
    "validation": {
      "installChecklist": [
        "Use the Yavira download entry.",
        "Review SKILL.md after the package is downloaded.",
        "Confirm the extracted package contains the expected setup assets."
      ],
      "postInstallChecks": [
        "Confirm the extracted package includes the expected docs or setup files.",
        "Validate the skill or prompts are available in your target agent workspace.",
        "Capture any manual follow-up steps the agent could not complete."
      ]
    },
    "downloadPageUrl": "https://openagent3.xyz/downloads/smb-sales-boost-leads",
    "agentPageUrl": "https://openagent3.xyz/skills/smb-sales-boost-leads/agent",
    "manifestUrl": "https://openagent3.xyz/skills/smb-sales-boost-leads/agent.json",
    "briefUrl": "https://openagent3.xyz/skills/smb-sales-boost-leads/agent.md"
  },
  "agentAssist": {
    "summary": "Hand the extracted package to your coding agent with a concrete install brief instead of figuring it out manually.",
    "steps": [
      "Download the package from Yavira.",
      "Extract it into a folder your agent can access.",
      "Paste one of the prompts below and point your agent at the extracted folder."
    ],
    "prompts": [
      {
        "label": "New install",
        "body": "I downloaded a skill package from Yavira. Read SKILL.md from the extracted folder and install it by following the included instructions. Then review README.md for any prerequisites, environment setup, or post-install checks. Tell me what you changed and call out any manual steps you could not complete."
      },
      {
        "label": "Upgrade existing",
        "body": "I downloaded an updated skill package from Yavira. Read SKILL.md from the extracted folder, compare it with my current installation, and upgrade it while preserving any custom configuration unless the package docs explicitly say otherwise. Then review README.md for any prerequisites, environment setup, or post-install checks. Summarize what changed and any follow-up checks I should run."
      }
    ]
  },
  "documentation": {
    "source": "clawhub",
    "primaryDoc": "SKILL.md",
    "sections": [
      {
        "title": "SMB Sales Boost Skill",
        "body": "This skill enables natural language interaction with the SMB Sales Boost API — a B2B lead generation platform providing access to newly registered small and medium businesses across the United States."
      },
      {
        "title": "Setup",
        "body": "The user must provide their API key. Keys have a smbk_ prefix and are generated from the Dashboard > API tab. The key is passed as a Bearer token in the Authorization header of every request.\n\nBase URL: https://smbsalesboost.com/api/v1\n\nImportant: API access requires a Starter, Growth, Scale, Platinum, or Enterprise subscription plan. New users can purchase a subscription entirely via API using the Programmatic Purchase endpoints (no web signup required)."
      },
      {
        "title": "Authentication",
        "body": "All requests must include:\n\nAuthorization: Bearer <API_KEY>\n\nIf the user hasn't provided their API key yet, ask them for it before making any requests. Store it in a variable for reuse throughout the session."
      },
      {
        "title": "Credit-Based System",
        "body": "Starter, Growth, and Scale plans use a credit-based model for lead exports:\n\nEach net-new lead exported deducts 1 credit\nPreviously-exported leads are free (do not consume credits)\nPlatinum and Enterprise plans are not credit-limited\n\nCredit Pricing (per credit):\n\nPlanCost per CreditStarter$0.10Growth$0.08Scale$0.05Platinum$0.03Enterprise$0.02\n\nUsers can purchase additional permanent credits via POST /purchase-credits."
      },
      {
        "title": "Rate Limits",
        "body": "Exports: 1 per 5 minutes\nEmail schedule trigger: 1 per 5 minutes\nAI category suggestions: 5 per minute\nAI keyword generation: 5 per minute\nAI auto-refine enable: 5 per minute\nAI auto-refine disable: 60 per minute\nAI auto-refine status: 60 per minute\nAI keyword status: 60 per minute\nProgrammatic purchase: 5 per hour per IP\nClaim key: 30 per hour per IP\n\nRate limit headers are returned on every response: X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset. If rate limited, check the Retry-After header for seconds to wait."
      },
      {
        "title": "Two Database Types",
        "body": "SMB Sales Boost has two separate databases with different contact information available:\n\nhome_improvement — Home improvement/contractor businesses with phone numbers, star ratings, review counts, review snippets, profile URLs, and categories\nother — General newly registered businesses with phone numbers and email addresses, registered URLs, crawled URLs, short/long descriptions, and redirect status\n\nThe Home Improvement database provides phone numbers as the primary contact method. The Other database provides both phone numbers and email addresses, making it ideal for cold email and multi-channel outreach campaigns.\n\nSome filter parameters only work with one database type. The user's account has a default database setting. Always check which database the user wants to query."
      },
      {
        "title": "1. Search Leads — GET /leads",
        "body": "The primary endpoint. Translates natural language queries into filtered lead searches.\n\nKey Parameters:\n\nParameterTypeDescriptionpageintegerPage number (default: 1)limitintegerResults per page (max 1000, default 100)databasestringhome_improvement or otherpositiveKeywordsJSON array stringKeywords to include (OR logic). Supports * wildcard for pattern matching (e.g., [\"*dental*\", \"*ortho*\"]). Without wildcards, performs substring matching by default.negativeKeywordsJSON array stringKeywords to exclude (AND logic). Also supports * wildcard (e.g., [\"*franchise*\"]).orColumnsJSON array stringColumn names to search keywords againstsearchstringFull-text search across all fieldsstateIncludestringComma-separated state codes: CA,NY,TXstateExcludestringComma-separated state codes to excludecityIncludeJSON array stringCities to includecityExcludeJSON array stringCities to excludezipIncludeJSON array stringZIP codes to includezipExcludeJSON array stringZIP codes to excludenameIncludeTermsJSON array stringBusiness name include termsnameExcludeTermsJSON array stringBusiness name exclude termslastUpdatedFromdate stringFilter by Last Updated date (after this date). Supports ISO 8601 or relative format (e.g., rel:7d, rel:6m).lastUpdatedTodate stringFilter by Last Updated date (before this date)updateReasonFilterstringComma-separated update reasons to filter by (e.g., \"Newly Added\", \"Phone Primary\")\n\nUnderstanding \"Last Updated\" — this is critical for finding the freshest leads:\n\nHome Improvement leads: Last Updated means a new phone number was detected\nOther leads: Last Updated means any of the 5 contact/address fields changed: primary phone, secondary phone, primary email, secondary email, or full address\nBoth databases also include newly added records in this date\nMany businesses launch a website before adding contact info, so the Last Updated date captures when that information first becomes available — making it the primary way to identify the most actionable leads\n\nParameterTypeDescriptioncountryIncludeJSON array stringCountries to includecountryExcludeJSON array stringCountries to excludesortBystringField to sort bysortOrderstringasc or desc (default: desc)\n\nWildcard Keyword Tips:\n\nUse * to match any characters: \"*dental*\" matches \"dental clinic\", \"pediatric dentistry\", etc.\nCombine wildcards for compound terms: \"*auto*repair*\" matches \"auto body repair\", \"automotive repair shop\", etc.\nUse multiple keyword variations for broader coverage: [\"*dental*\", \"*dentist*\", \"*orthodont*\"]\nKeywords without wildcards still perform substring matching by default\n\nHome Improvement Only:\n\nParameterTypeDescriptionminStars / maxStarsnumberStar rating rangeminReviewCount / maxReviewCountintegerReview count rangecategoriesIncludeTerms / categoriesExcludeTermsJSON array stringCategory filtersreviewSnippetIncludeTerms / reviewSnippetExcludeTermsJSON array stringReview text filtersprofileUrlIncludeTerms / profileUrlExcludeTermsJSON array stringProfile URL filters\n\nOther Database Only:\n\nParameterTypeDescriptionurlIncludeTerms / urlExcludeTermsJSON array stringRegistered URL filterscrawledUrlIncludeTerms / crawledUrlExcludeTermsJSON array stringCrawled URL filtersdescriptionIncludeTerms / descriptionExcludeTermsJSON array stringShort description filtersdescriptionLongIncludeTerms / descriptionLongExcludeTermsJSON array stringLong description filtersemailPrimaryInclude / emailPrimaryExcludeJSON array stringPrimary email filtersemailSecondaryInclude / emailSecondaryExcludeJSON array stringSecondary email filtersphonePrimaryInclude / phonePrimaryExcludeJSON array stringPrimary phone filtersphoneSecondaryInclude / phoneSecondaryExcludeJSON array stringSecondary phone filtersredirectFilterstringyes or no — filter by redirect statusregistrationDateFrom / registrationDateTodate stringFilter by domain registration date (ISO 8601 or relative format e.g., rel:6m)timeScrapedFrom / timeScrapedTodate stringFilter by when leads were scraped (ISO 8601 or relative format e.g., rel:30d)websiteSchemaFilterstringComma-separated website schema types (e.g., LocalBusiness,Organization). Use GET /leads/other/schema-types for available values.\n\nImportant: At least one positive filter is required (positiveKeywords or any column-specific include terms).\n\nResponse includes: leads array, totalCount, page, limit, databaseType\n\nLead fields: id, companyName, state, city, zip, phone, email, categories, lastUpdated (phone/email masked for free users). The lastUpdated field indicates when contact information was last detected or updated — this is the best indicator of lead freshness and actionability."
      },
      {
        "title": "2. Website Schema Types — GET /leads/other/schema-types",
        "body": "Returns a sorted list of all distinct website schema types found in the Other leads database. Use these values with the websiteSchemaFilter parameter on GET /leads."
      },
      {
        "title": "3. Export Leads — POST /leads/export",
        "body": "Export filtered leads as CSV, JSON, or XLSX files.\n\nRequest body:\n\n{\n  \"database\": \"home_improvement\" | \"other\",\n  \"filters\": { /* same filter params as GET /leads */ },\n  \"selectedIds\": [1, 2, 3],  // alternative to filters\n  \"formatId\": 123,  // optional export format template ID\n  \"maxLeads\": 500,  // optional: cap leads per export, overflow stored in reservoir\n  \"maxResults\": 1000,  // optional: total leads (new + previously-exported)\n  \"maxCredits\": 100  // optional: credit spending cap (0 = only previously-exported leads)\n}\n\nCredit system (Starter/Growth/Scale plans):\n\nEach net-new lead exported deducts 1 credit\nPreviously-exported leads are included for free\nUse maxCredits to control spending, maxLeads to limit volume\nSet maxCredits: 0 to only receive previously-exported leads at no cost\n\nResponse: files array (with base64-encoded data), leadCount, exportId, databaseType, creditsUsed, creditsRemaining, overflowCount\n\nError 402 Payment Required: Returned when credit-plan users have insufficient credits.\n\nRate limited: 1 export per 5 minutes, max 10,000 leads per export."
      },
      {
        "title": "4. Filter Presets — /filter-presets",
        "body": "GET /filter-presets — List all saved presets\nPOST /filter-presets — Create a preset (requires name and filters object)\nDELETE /filter-presets/{id} — Delete a preset"
      },
      {
        "title": "5. Keyword Lists — /keyword-lists",
        "body": "Keyword lists now support typed lists (positive or negative) with paired list management and source categories.\n\nGET /keyword-lists — List all keyword lists\nPOST /keyword-lists — Create (requires name, optional keywords array, sourceCategories array max 3)\nPUT /keyword-lists/{id} — Update\nDELETE /keyword-lists/{id} — Delete\n\nKeyword list properties: name, keywords (wildcard patterns e.g., *dentist*), type (positive/negative), pairedListId (linked positive/negative pair), sourceCategories (max 3), autoRefineEnabled, refinementStatus (running/completed/paused)"
      },
      {
        "title": "6. Email Schedules — /email-schedules",
        "body": "Email schedules now support distribution modes and lead reservoirs.\n\nGET /email-schedules — List schedules\nPOST /email-schedules — Create (requires name, filterPresetId, intervalValue, intervalUnit, recipients min 1)\nPATCH /email-schedules/{id} — Update (supports isActive toggle)\nDELETE /email-schedules/{id} — Delete\nPOST /email-schedules/{id}/trigger — Manually trigger an active schedule to send immediately (rate limited: 1 per 5 minutes)\n\nDistribution modes:\n\nfull_copy (default): All leads sent to every recipient\nsplit_evenly: Leads divided evenly among recipients. Optional fullCopyRecipients array for people who should receive the full list (e.g., managers)\n\nLead reservoir: Set maxLeadsPerEmail to cap leads per delivery. Overflow is stored and included in the next scheduled email."
      },
      {
        "title": "7. Export Formats — /export-formats",
        "body": "GET /export-formats — List custom export formats\nPOST /export-formats — Create (requires name, supports fileType, fieldMappings, split settings)\nGET /export-formats/{id} — Get specific format\nPATCH /export-formats/{id} — Update\nDELETE /export-formats/{id} — Delete\nPOST /export-formats/{id}/set-default — Set as default"
      },
      {
        "title": "8. Export History — /export-history",
        "body": "GET /export-history — List past exports (optional limit param, default 50)\nGET /export-history/{id}/download — Re-download (expires after 7 days)"
      },
      {
        "title": "9. AI Features",
        "body": "POST /ai/suggest-categories — Get AI category suggestions based on company profile.\n\nRequired: companyName, companyDescription, productService\nOptional: companyWebsite, smbType, excludeCategories\n\nPOST /ai/generate-keywords — Trigger async keyword generation based on your company profile and target categories (up to 3 per list). Keywords are generated as wildcard patterns and saved to keyword lists with auto-refine enabled by default. Use /ai/keyword-status to check progress.\n\nGET /ai/keyword-status — Check the status of keyword generation jobs. Use this to poll for completion after triggering keyword generation.\n\nAI Auto-Refine — Single-pass 4-phase optimization that automatically refines keyword lists using AI:\n\nPhase 1: Validates positive keywords (50% threshold, up to 2 variation attempts)\nPhase 1B: Discovers up to 15 new positive keywords in a single AI call\nPhase 2: Validates negative keywords (40% threshold)\nPhase 2B: Discovers up to 5 new negative keywords from ~80 sample leads\nFinal quality score (1-10, median of 3) determines if a retry pass is needed\nAuto-refine turns off when complete\nUses sourceCategories (max 3 per list) for accurate AI scoring\n\nEndpoints:\n\nPOST /ai/auto-refine/enable — Enable auto-refine for a keyword list (requires listId)\nPOST /ai/auto-refine/disable — Disable auto-refine for a keyword list (requires listId)\nGET /ai/auto-refine/status — Check auto-refine status (optional listId query param to filter by specific list)"
      },
      {
        "title": "10. Export Blacklist — /export-blacklist",
        "body": "GET /export-blacklist — List blacklisted entries\nPOST /export-blacklist — Add entry (single or batch via entries array)\nDELETE /export-blacklist/{id} — Remove entry"
      },
      {
        "title": "11. Account",
        "body": "GET /me — Get user profile (subscription plan, settings, onboarding status, credit balance)\nPATCH /me — Update profile (firstName, lastName, companyName, companyWebsite)\nGET /settings/database — Check current database type and switch availability\nPOST /settings/switch-database — Switch between databases (has cooldown)"
      },
      {
        "title": "12. Programmatic Purchase — Buy a subscription via API",
        "body": "No web signup required. New users can purchase and get an API key entirely via API:\n\nPOST /purchase — Create a Stripe Checkout session. Provide email and plan (starter, growth, scale, platinum, or enterprise). Returns a checkoutUrl and claimToken.\nDirect the user to complete payment at the checkout URL.\nPOST /claim-key — After payment, provide email and claimToken to retrieve the API key. If payment is still pending, returns status pending — poll every 5-10 seconds."
      },
      {
        "title": "13. Credits & Subscription Management",
        "body": "POST /purchase-credits — Purchase additional permanent credits. Provide either creditCount (min 100) or dollarAmount (min $1). Uses saved payment method (Stripe off-session charge).\nPOST /subscription/change-plan — Upgrade or downgrade between starter, growth, and scale. On upgrade, unused monthly credits convert to permanent credits. Downgrades take effect at renewal.\nPOST /subscription/cancel — Cancel subscription at end of current billing period. Access continues until period ends."
      },
      {
        "title": "Natural Language Translation Guide",
        "body": "When users make natural language requests, translate them into API calls. Use multiple wildcard keyword variations to cast a wider net — keywords are matched via OR logic so more variations means better coverage:\n\nUser SaysAPI Call\"Find new dental practices in Texas\"GET /leads?positiveKeywords=[\"*dental*\",\"*dentist*\",\"*orthodont*\"]&stateInclude=TX\"Search for med spas and aesthetics businesses in Florida\"GET /leads?positiveKeywords=[\"*med*spa*\",\"*medical*spa*\",\"*aesthet*\",\"*botox*\",\"*medspa*\"]&stateInclude=FL\"Show me auto repair shops in Chicago updated this week\"GET /leads?positiveKeywords=[\"*auto*repair*\",\"*body*shop*\",\"*mechanic*\",\"*oil*change*\",\"*brake*\"]&cityInclude=[\"Chicago\"]&lastUpdatedFrom=rel:7d\"Find pet grooming businesses in California, exclude boarding\"GET /leads?positiveKeywords=[\"*pet*groom*\",\"*dog*groom*\",\"*pet*salon*\"]&negativeKeywords=[\"*boarding*\",\"*kennel*\"]&stateInclude=CA\"Get bakeries and catering companies in New York\"GET /leads?positiveKeywords=[\"*bakery*\",\"*bake*shop*\",\"*cater*\",\"*pastry*\",\"*cake*\"]&stateInclude=NY\"Find fitness studios in Georgia and North Carolina\"GET /leads?positiveKeywords=[\"*fitness*\",\"*gym*\",\"*yoga*\",\"*pilates*\",\"*crossfit*\"]&stateInclude=GA,NC\"Get 50 leads with high ratings\"GET /leads?limit=50&minStars=4 (home_improvement only)\"Find businesses with LocalBusiness schema type\"GET /leads?websiteSchemaFilter=LocalBusiness (other only)\"Show leads registered in the last 6 months\"GET /leads?registrationDateFrom=rel:6m (other only)\"Export all my filtered results\"POST /leads/export with current filters\"Export but only spend 50 credits max\"POST /leads/export with maxCredits: 50\"Export only previously-exported leads (free)\"POST /leads/export with maxCredits: 0\"What categories should I target?\"POST /ai/suggest-categories\"Save this search as 'FL Med Spas'\"POST /filter-presets\"Show my recent exports\"GET /export-history\"What plan am I on?\"GET /me\"How many credits do I have left?\"GET /me\"Buy 500 more credits\"POST /purchase-credits with creditCount: 500\"Upgrade to the Growth plan\"POST /subscription/change-plan with targetPlan: \"growth\"\"Cancel my subscription\"POST /subscription/cancel\"Exclude these domains from exports\"POST /export-blacklist\"Enable auto-refine on my keyword list\"POST /ai/auto-refine/enable with listId\"Check on my keyword generation\"GET /ai/keyword-status\"Send my scheduled email now\"POST /email-schedules/{id}/trigger\"Split leads evenly among my sales team\"POST /email-schedules with distributionMode: \"split_evenly\"\"I want to sign up for a Starter plan\"POST /purchase with plan: \"starter\""
      },
      {
        "title": "Building API Requests",
        "body": "Use the included smb_api.py script for all API calls. It handles authentication, URL encoding, response parsing, and safe file export in a single reusable file. Do not use shell commands like curl — constructing shell commands from user-provided input risks shell injection vulnerabilities."
      },
      {
        "title": "Usage",
        "body": "python smb_api.py <API_KEY> <METHOD> <ENDPOINT> [--params '{\"key\":\"value\"}'] [--body '{\"key\":\"value\"}'] [--output-dir /path/to/dir]"
      },
      {
        "title": "Examples",
        "body": "# Search for med spas in Florida using wildcard keywords (OR logic)\npython smb_api.py smbk_xxx GET /leads --params '{\"positiveKeywords\":\"[\\\"*med*spa*\\\",\\\"*medical*spa*\\\",\\\"*aesthet*\\\",\\\"*botox*\\\",\\\"*medspa*\\\"]\",\"stateInclude\":\"FL\",\"limit\":\"25\"}'\n\n# Find auto shops in multiple states, exclude franchises\npython smb_api.py smbk_xxx GET /leads --params '{\"positiveKeywords\":\"[\\\"*auto*repair*\\\",\\\"*body*shop*\\\",\\\"*mechanic*\\\",\\\"*tire*\\\",\\\"*oil*change*\\\"]\",\"negativeKeywords\":\"[\\\"*franchise*\\\",\\\"*jiffy*\\\"]\",\"stateInclude\":\"GA,FL,NC,SC,TN\",\"limit\":\"50\"}'\n\n# Search for recently updated dental leads in Texas\npython smb_api.py smbk_xxx GET /leads --params '{\"positiveKeywords\":\"[\\\"*dental*\\\",\\\"*dentist*\\\",\\\"*orthodont*\\\",\\\"*oral*surg*\\\"]\",\"stateInclude\":\"TX\",\"lastUpdatedFrom\":\"rel:7d\"}'\n\n# Full-text search across all fields\npython smb_api.py smbk_xxx GET /leads --params '{\"search\":\"organic coffee\",\"limit\":\"25\"}'\n\n# Filter by website schema type (other database only)\npython smb_api.py smbk_xxx GET /leads --params '{\"websiteSchemaFilter\":\"LocalBusiness\",\"stateInclude\":\"CA\",\"limit\":\"25\"}'\n\n# Get available website schema types\npython smb_api.py smbk_xxx GET /leads/other/schema-types\n\n# Get account info (includes credit balance)\npython smb_api.py smbk_xxx GET /me\n\n# Export with credit controls\npython smb_api.py smbk_xxx POST /leads/export --body '{\"database\":\"other\",\"filters\":{\"positiveKeywords\":[\"*pet*groom*\",\"*veterinar*\",\"*dog*train*\"],\"stateInclude\":\"CA,OR,WA\"},\"maxCredits\":100}'\n\n# Export only previously-exported leads (free, no credits used)\npython smb_api.py smbk_xxx POST /leads/export --body '{\"database\":\"other\",\"filters\":{\"positiveKeywords\":[\"*dental*\"],\"stateInclude\":\"TX\"},\"maxCredits\":0}'\n\n# Purchase additional credits\npython smb_api.py smbk_xxx POST /purchase-credits --body '{\"creditCount\":500}'\n\n# Purchase credits by dollar amount\npython smb_api.py smbk_xxx POST /purchase-credits --body '{\"dollarAmount\":50}'\n\n# Change subscription plan\npython smb_api.py smbk_xxx POST /subscription/change-plan --body '{\"targetPlan\":\"growth\"}'\n\n# Cancel subscription\npython smb_api.py smbk_xxx POST /subscription/cancel\n\n# Start a programmatic purchase (no auth needed, but script still requires a placeholder key)\npython smb_api.py none POST /purchase --body '{\"email\":\"user@example.com\",\"plan\":\"starter\"}'\n\n# Claim API key after payment\npython smb_api.py none POST /claim-key --body '{\"email\":\"user@example.com\",\"claimToken\":\"tok_abc123\"}'\n\n# AI category suggestions\npython smb_api.py smbk_xxx POST /ai/suggest-categories --body '{\"companyName\":\"FitPro Supply\",\"companyDescription\":\"Commercial fitness equipment distributor\",\"productService\":\"Gym equipment, treadmills, weight systems\"}'\n\n# Create a filter preset\npython smb_api.py smbk_xxx POST /filter-presets --body '{\"name\":\"NY Bakeries\",\"filters\":{\"positiveKeywords\":[\"*bakery*\",\"*bake*shop*\",\"*cater*\",\"*pastry*\"],\"stateInclude\":\"NY\"}}'\n\n# Create email schedule with split distribution\npython smb_api.py smbk_xxx POST /email-schedules --body '{\"name\":\"Daily TX Leads\",\"filterPresetId\":5,\"intervalValue\":1,\"intervalUnit\":\"days\",\"recipients\":[\"rep1@co.com\",\"rep2@co.com\"],\"distributionMode\":\"split_evenly\",\"fullCopyRecipients\":[\"manager@co.com\"],\"maxLeadsPerEmail\":50}'\n\n# Enable AI auto-refine on a keyword list\npython smb_api.py smbk_xxx POST /ai/auto-refine/enable --body '{\"listId\":42}'\n\n# Check auto-refine status for a specific list\npython smb_api.py smbk_xxx GET /ai/auto-refine/status --params '{\"listId\":\"42\"}'\n\n# Check keyword generation job status\npython smb_api.py smbk_xxx GET /ai/keyword-status\n\n# Manually trigger an email schedule\npython smb_api.py smbk_xxx POST /email-schedules/15/trigger\n\n# Delete a filter preset\npython smb_api.py smbk_xxx DELETE /filter-presets/42\n\nThe script outputs JSON to stdout and rate limit headers to stderr. For export requests, files are automatically saved with sanitized filenames.\n\nRemember:\n\nUse multiple wildcard keyword variations to cast a wider net (e.g., [\"*dental*\", \"*dentist*\", \"*orthodont*\"] not just [\"dental\"]) — keywords are matched via OR logic\nUse * for flexible pattern matching: \"*auto*repair*\" matches \"auto body repair\", \"automotive repair shop\", etc.\nJSON array parameters should be serialized as strings inside the --params JSON\nAt least one positive filter is required for lead searches\nCheck which database the user needs before applying database-specific filters\nHome Improvement database provides phone numbers; Other database provides phone numbers and email addresses\nPhone and email are masked for free-tier users\nPresent results in a clean, readable table format\nFor credit-plan users, mention credits used/remaining after exports\nThe POST /purchase and POST /claim-key endpoints do not require authentication (no API key needed)"
      },
      {
        "title": "Security",
        "body": "This skill addresses two specific agent execution risks: shell injection from constructing CLI commands with user input, and arbitrary file writes from unsanitized API-provided filenames.\n\nShell injection prevention: The smb_api.py script uses Python's requests library for all HTTP calls. User-provided search terms, locations, and other inputs are passed as structured function arguments — never interpolated into shell command strings. This eliminates the shell injection vector that exists when agents construct curl commands from user input.\n\nPath traversal prevention in exports: The /leads/export endpoint returns base64-encoded files with an API-provided fileName field. A malicious or corrupted filename (e.g., ../../etc/passwd) could write files to arbitrary locations. The script enforces three safeguards:\n\nBasename extraction: os.path.basename() strips all directory components — ../../etc/passwd becomes passwd\nExtension validation: Only .csv, .json, and .xlsx extensions are allowed; anything else defaults to .csv\nScoped output directory: Files are written only to the designated output directory (/mnt/user-data/outputs/ by default), never to user-specified or API-specified paths\n\nAPI key handling: The key is passed as a CLI argument and sent only in the Authorization header. It is never logged, written to files, or included in error output."
      },
      {
        "title": "Error Handling",
        "body": "StatusMeaning400Bad request — check parameters401Invalid or missing API key402Insufficient credits (credit-plan users) — check credit balance with GET /me403Active subscription required404Resource not found429Rate limited — check Retry-After header500Server error\n\nAll errors return: { \"error\": \"error_code\", \"message\": \"Human-readable message\" }"
      }
    ],
    "body": "SMB Sales Boost Skill\n\nThis skill enables natural language interaction with the SMB Sales Boost API — a B2B lead generation platform providing access to newly registered small and medium businesses across the United States.\n\nSetup\n\nThe user must provide their API key. Keys have a smbk_ prefix and are generated from the Dashboard > API tab. The key is passed as a Bearer token in the Authorization header of every request.\n\nBase URL: https://smbsalesboost.com/api/v1\n\nImportant: API access requires a Starter, Growth, Scale, Platinum, or Enterprise subscription plan. New users can purchase a subscription entirely via API using the Programmatic Purchase endpoints (no web signup required).\n\nAuthentication\n\nAll requests must include:\n\nAuthorization: Bearer <API_KEY>\n\n\nIf the user hasn't provided their API key yet, ask them for it before making any requests. Store it in a variable for reuse throughout the session.\n\nCredit-Based System\n\nStarter, Growth, and Scale plans use a credit-based model for lead exports:\n\nEach net-new lead exported deducts 1 credit\nPreviously-exported leads are free (do not consume credits)\nPlatinum and Enterprise plans are not credit-limited\n\nCredit Pricing (per credit):\n\nPlan\tCost per Credit\nStarter\t$0.10\nGrowth\t$0.08\nScale\t$0.05\nPlatinum\t$0.03\nEnterprise\t$0.02\n\nUsers can purchase additional permanent credits via POST /purchase-credits.\n\nRate Limits\nExports: 1 per 5 minutes\nEmail schedule trigger: 1 per 5 minutes\nAI category suggestions: 5 per minute\nAI keyword generation: 5 per minute\nAI auto-refine enable: 5 per minute\nAI auto-refine disable: 60 per minute\nAI auto-refine status: 60 per minute\nAI keyword status: 60 per minute\nProgrammatic purchase: 5 per hour per IP\nClaim key: 30 per hour per IP\n\nRate limit headers are returned on every response: X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset. If rate limited, check the Retry-After header for seconds to wait.\n\nTwo Database Types\n\nSMB Sales Boost has two separate databases with different contact information available:\n\nhome_improvement — Home improvement/contractor businesses with phone numbers, star ratings, review counts, review snippets, profile URLs, and categories\nother — General newly registered businesses with phone numbers and email addresses, registered URLs, crawled URLs, short/long descriptions, and redirect status\n\nThe Home Improvement database provides phone numbers as the primary contact method. The Other database provides both phone numbers and email addresses, making it ideal for cold email and multi-channel outreach campaigns.\n\nSome filter parameters only work with one database type. The user's account has a default database setting. Always check which database the user wants to query.\n\nCore Endpoints\n1. Search Leads — GET /leads\n\nThe primary endpoint. Translates natural language queries into filtered lead searches.\n\nKey Parameters:\n\nParameter\tType\tDescription\npage\tinteger\tPage number (default: 1)\nlimit\tinteger\tResults per page (max 1000, default 100)\ndatabase\tstring\thome_improvement or other\npositiveKeywords\tJSON array string\tKeywords to include (OR logic). Supports * wildcard for pattern matching (e.g., [\"*dental*\", \"*ortho*\"]). Without wildcards, performs substring matching by default.\nnegativeKeywords\tJSON array string\tKeywords to exclude (AND logic). Also supports * wildcard (e.g., [\"*franchise*\"]).\norColumns\tJSON array string\tColumn names to search keywords against\nsearch\tstring\tFull-text search across all fields\nstateInclude\tstring\tComma-separated state codes: CA,NY,TX\nstateExclude\tstring\tComma-separated state codes to exclude\ncityInclude\tJSON array string\tCities to include\ncityExclude\tJSON array string\tCities to exclude\nzipInclude\tJSON array string\tZIP codes to include\nzipExclude\tJSON array string\tZIP codes to exclude\nnameIncludeTerms\tJSON array string\tBusiness name include terms\nnameExcludeTerms\tJSON array string\tBusiness name exclude terms\nlastUpdatedFrom\tdate string\tFilter by Last Updated date (after this date). Supports ISO 8601 or relative format (e.g., rel:7d, rel:6m).\nlastUpdatedTo\tdate string\tFilter by Last Updated date (before this date)\nupdateReasonFilter\tstring\tComma-separated update reasons to filter by (e.g., \"Newly Added\", \"Phone Primary\")\n\nUnderstanding \"Last Updated\" — this is critical for finding the freshest leads:\n\nHome Improvement leads: Last Updated means a new phone number was detected\nOther leads: Last Updated means any of the 5 contact/address fields changed: primary phone, secondary phone, primary email, secondary email, or full address\nBoth databases also include newly added records in this date\nMany businesses launch a website before adding contact info, so the Last Updated date captures when that information first becomes available — making it the primary way to identify the most actionable leads\nParameter\tType\tDescription\ncountryInclude\tJSON array string\tCountries to include\ncountryExclude\tJSON array string\tCountries to exclude\nsortBy\tstring\tField to sort by\nsortOrder\tstring\tasc or desc (default: desc)\n\nWildcard Keyword Tips:\n\nUse * to match any characters: \"*dental*\" matches \"dental clinic\", \"pediatric dentistry\", etc.\nCombine wildcards for compound terms: \"*auto*repair*\" matches \"auto body repair\", \"automotive repair shop\", etc.\nUse multiple keyword variations for broader coverage: [\"*dental*\", \"*dentist*\", \"*orthodont*\"]\nKeywords without wildcards still perform substring matching by default\n\nHome Improvement Only:\n\nParameter\tType\tDescription\nminStars / maxStars\tnumber\tStar rating range\nminReviewCount / maxReviewCount\tinteger\tReview count range\ncategoriesIncludeTerms / categoriesExcludeTerms\tJSON array string\tCategory filters\nreviewSnippetIncludeTerms / reviewSnippetExcludeTerms\tJSON array string\tReview text filters\nprofileUrlIncludeTerms / profileUrlExcludeTerms\tJSON array string\tProfile URL filters\n\nOther Database Only:\n\nParameter\tType\tDescription\nurlIncludeTerms / urlExcludeTerms\tJSON array string\tRegistered URL filters\ncrawledUrlIncludeTerms / crawledUrlExcludeTerms\tJSON array string\tCrawled URL filters\ndescriptionIncludeTerms / descriptionExcludeTerms\tJSON array string\tShort description filters\ndescriptionLongIncludeTerms / descriptionLongExcludeTerms\tJSON array string\tLong description filters\nemailPrimaryInclude / emailPrimaryExclude\tJSON array string\tPrimary email filters\nemailSecondaryInclude / emailSecondaryExclude\tJSON array string\tSecondary email filters\nphonePrimaryInclude / phonePrimaryExclude\tJSON array string\tPrimary phone filters\nphoneSecondaryInclude / phoneSecondaryExclude\tJSON array string\tSecondary phone filters\nredirectFilter\tstring\tyes or no — filter by redirect status\nregistrationDateFrom / registrationDateTo\tdate string\tFilter by domain registration date (ISO 8601 or relative format e.g., rel:6m)\ntimeScrapedFrom / timeScrapedTo\tdate string\tFilter by when leads were scraped (ISO 8601 or relative format e.g., rel:30d)\nwebsiteSchemaFilter\tstring\tComma-separated website schema types (e.g., LocalBusiness,Organization). Use GET /leads/other/schema-types for available values.\n\nImportant: At least one positive filter is required (positiveKeywords or any column-specific include terms).\n\nResponse includes: leads array, totalCount, page, limit, databaseType\n\nLead fields: id, companyName, state, city, zip, phone, email, categories, lastUpdated (phone/email masked for free users). The lastUpdated field indicates when contact information was last detected or updated — this is the best indicator of lead freshness and actionability.\n\n2. Website Schema Types — GET /leads/other/schema-types\n\nReturns a sorted list of all distinct website schema types found in the Other leads database. Use these values with the websiteSchemaFilter parameter on GET /leads.\n\n3. Export Leads — POST /leads/export\n\nExport filtered leads as CSV, JSON, or XLSX files.\n\nRequest body:\n\n{\n  \"database\": \"home_improvement\" | \"other\",\n  \"filters\": { /* same filter params as GET /leads */ },\n  \"selectedIds\": [1, 2, 3],  // alternative to filters\n  \"formatId\": 123,  // optional export format template ID\n  \"maxLeads\": 500,  // optional: cap leads per export, overflow stored in reservoir\n  \"maxResults\": 1000,  // optional: total leads (new + previously-exported)\n  \"maxCredits\": 100  // optional: credit spending cap (0 = only previously-exported leads)\n}\n\n\nCredit system (Starter/Growth/Scale plans):\n\nEach net-new lead exported deducts 1 credit\nPreviously-exported leads are included for free\nUse maxCredits to control spending, maxLeads to limit volume\nSet maxCredits: 0 to only receive previously-exported leads at no cost\n\nResponse: files array (with base64-encoded data), leadCount, exportId, databaseType, creditsUsed, creditsRemaining, overflowCount\n\nError 402 Payment Required: Returned when credit-plan users have insufficient credits.\n\nRate limited: 1 export per 5 minutes, max 10,000 leads per export.\n\n4. Filter Presets — /filter-presets\nGET /filter-presets — List all saved presets\nPOST /filter-presets — Create a preset (requires name and filters object)\nDELETE /filter-presets/{id} — Delete a preset\n5. Keyword Lists — /keyword-lists\n\nKeyword lists now support typed lists (positive or negative) with paired list management and source categories.\n\nGET /keyword-lists — List all keyword lists\nPOST /keyword-lists — Create (requires name, optional keywords array, sourceCategories array max 3)\nPUT /keyword-lists/{id} — Update\nDELETE /keyword-lists/{id} — Delete\n\nKeyword list properties: name, keywords (wildcard patterns e.g., *dentist*), type (positive/negative), pairedListId (linked positive/negative pair), sourceCategories (max 3), autoRefineEnabled, refinementStatus (running/completed/paused)\n\n6. Email Schedules — /email-schedules\n\nEmail schedules now support distribution modes and lead reservoirs.\n\nGET /email-schedules — List schedules\nPOST /email-schedules — Create (requires name, filterPresetId, intervalValue, intervalUnit, recipients min 1)\nPATCH /email-schedules/{id} — Update (supports isActive toggle)\nDELETE /email-schedules/{id} — Delete\nPOST /email-schedules/{id}/trigger — Manually trigger an active schedule to send immediately (rate limited: 1 per 5 minutes)\n\nDistribution modes:\n\nfull_copy (default): All leads sent to every recipient\nsplit_evenly: Leads divided evenly among recipients. Optional fullCopyRecipients array for people who should receive the full list (e.g., managers)\n\nLead reservoir: Set maxLeadsPerEmail to cap leads per delivery. Overflow is stored and included in the next scheduled email.\n\n7. Export Formats — /export-formats\nGET /export-formats — List custom export formats\nPOST /export-formats — Create (requires name, supports fileType, fieldMappings, split settings)\nGET /export-formats/{id} — Get specific format\nPATCH /export-formats/{id} — Update\nDELETE /export-formats/{id} — Delete\nPOST /export-formats/{id}/set-default — Set as default\n8. Export History — /export-history\nGET /export-history — List past exports (optional limit param, default 50)\nGET /export-history/{id}/download — Re-download (expires after 7 days)\n9. AI Features\n\nPOST /ai/suggest-categories — Get AI category suggestions based on company profile.\n\nRequired: companyName, companyDescription, productService Optional: companyWebsite, smbType, excludeCategories\n\nPOST /ai/generate-keywords — Trigger async keyword generation based on your company profile and target categories (up to 3 per list). Keywords are generated as wildcard patterns and saved to keyword lists with auto-refine enabled by default. Use /ai/keyword-status to check progress.\n\nGET /ai/keyword-status — Check the status of keyword generation jobs. Use this to poll for completion after triggering keyword generation.\n\nAI Auto-Refine — Single-pass 4-phase optimization that automatically refines keyword lists using AI:\n\nPhase 1: Validates positive keywords (50% threshold, up to 2 variation attempts)\nPhase 1B: Discovers up to 15 new positive keywords in a single AI call\nPhase 2: Validates negative keywords (40% threshold)\nPhase 2B: Discovers up to 5 new negative keywords from ~80 sample leads\nFinal quality score (1-10, median of 3) determines if a retry pass is needed\nAuto-refine turns off when complete\nUses sourceCategories (max 3 per list) for accurate AI scoring\n\nEndpoints:\n\nPOST /ai/auto-refine/enable — Enable auto-refine for a keyword list (requires listId)\nPOST /ai/auto-refine/disable — Disable auto-refine for a keyword list (requires listId)\nGET /ai/auto-refine/status — Check auto-refine status (optional listId query param to filter by specific list)\n10. Export Blacklist — /export-blacklist\nGET /export-blacklist — List blacklisted entries\nPOST /export-blacklist — Add entry (single or batch via entries array)\nDELETE /export-blacklist/{id} — Remove entry\n11. Account\nGET /me — Get user profile (subscription plan, settings, onboarding status, credit balance)\nPATCH /me — Update profile (firstName, lastName, companyName, companyWebsite)\nGET /settings/database — Check current database type and switch availability\nPOST /settings/switch-database — Switch between databases (has cooldown)\n12. Programmatic Purchase — Buy a subscription via API\n\nNo web signup required. New users can purchase and get an API key entirely via API:\n\nPOST /purchase — Create a Stripe Checkout session. Provide email and plan (starter, growth, scale, platinum, or enterprise). Returns a checkoutUrl and claimToken.\nDirect the user to complete payment at the checkout URL.\nPOST /claim-key — After payment, provide email and claimToken to retrieve the API key. If payment is still pending, returns status pending — poll every 5-10 seconds.\n13. Credits & Subscription Management\nPOST /purchase-credits — Purchase additional permanent credits. Provide either creditCount (min 100) or dollarAmount (min $1). Uses saved payment method (Stripe off-session charge).\nPOST /subscription/change-plan — Upgrade or downgrade between starter, growth, and scale. On upgrade, unused monthly credits convert to permanent credits. Downgrades take effect at renewal.\nPOST /subscription/cancel — Cancel subscription at end of current billing period. Access continues until period ends.\nNatural Language Translation Guide\n\nWhen users make natural language requests, translate them into API calls. Use multiple wildcard keyword variations to cast a wider net — keywords are matched via OR logic so more variations means better coverage:\n\nUser Says\tAPI Call\n\"Find new dental practices in Texas\"\tGET /leads?positiveKeywords=[\"*dental*\",\"*dentist*\",\"*orthodont*\"]&stateInclude=TX\n\"Search for med spas and aesthetics businesses in Florida\"\tGET /leads?positiveKeywords=[\"*med*spa*\",\"*medical*spa*\",\"*aesthet*\",\"*botox*\",\"*medspa*\"]&stateInclude=FL\n\"Show me auto repair shops in Chicago updated this week\"\tGET /leads?positiveKeywords=[\"*auto*repair*\",\"*body*shop*\",\"*mechanic*\",\"*oil*change*\",\"*brake*\"]&cityInclude=[\"Chicago\"]&lastUpdatedFrom=rel:7d\n\"Find pet grooming businesses in California, exclude boarding\"\tGET /leads?positiveKeywords=[\"*pet*groom*\",\"*dog*groom*\",\"*pet*salon*\"]&negativeKeywords=[\"*boarding*\",\"*kennel*\"]&stateInclude=CA\n\"Get bakeries and catering companies in New York\"\tGET /leads?positiveKeywords=[\"*bakery*\",\"*bake*shop*\",\"*cater*\",\"*pastry*\",\"*cake*\"]&stateInclude=NY\n\"Find fitness studios in Georgia and North Carolina\"\tGET /leads?positiveKeywords=[\"*fitness*\",\"*gym*\",\"*yoga*\",\"*pilates*\",\"*crossfit*\"]&stateInclude=GA,NC\n\"Get 50 leads with high ratings\"\tGET /leads?limit=50&minStars=4 (home_improvement only)\n\"Find businesses with LocalBusiness schema type\"\tGET /leads?websiteSchemaFilter=LocalBusiness (other only)\n\"Show leads registered in the last 6 months\"\tGET /leads?registrationDateFrom=rel:6m (other only)\n\"Export all my filtered results\"\tPOST /leads/export with current filters\n\"Export but only spend 50 credits max\"\tPOST /leads/export with maxCredits: 50\n\"Export only previously-exported leads (free)\"\tPOST /leads/export with maxCredits: 0\n\"What categories should I target?\"\tPOST /ai/suggest-categories\n\"Save this search as 'FL Med Spas'\"\tPOST /filter-presets\n\"Show my recent exports\"\tGET /export-history\n\"What plan am I on?\"\tGET /me\n\"How many credits do I have left?\"\tGET /me\n\"Buy 500 more credits\"\tPOST /purchase-credits with creditCount: 500\n\"Upgrade to the Growth plan\"\tPOST /subscription/change-plan with targetPlan: \"growth\"\n\"Cancel my subscription\"\tPOST /subscription/cancel\n\"Exclude these domains from exports\"\tPOST /export-blacklist\n\"Enable auto-refine on my keyword list\"\tPOST /ai/auto-refine/enable with listId\n\"Check on my keyword generation\"\tGET /ai/keyword-status\n\"Send my scheduled email now\"\tPOST /email-schedules/{id}/trigger\n\"Split leads evenly among my sales team\"\tPOST /email-schedules with distributionMode: \"split_evenly\"\n\"I want to sign up for a Starter plan\"\tPOST /purchase with plan: \"starter\"\nBuilding API Requests\n\nUse the included smb_api.py script for all API calls. It handles authentication, URL encoding, response parsing, and safe file export in a single reusable file. Do not use shell commands like curl — constructing shell commands from user-provided input risks shell injection vulnerabilities.\n\nUsage\npython smb_api.py <API_KEY> <METHOD> <ENDPOINT> [--params '{\"key\":\"value\"}'] [--body '{\"key\":\"value\"}'] [--output-dir /path/to/dir]\n\nExamples\n# Search for med spas in Florida using wildcard keywords (OR logic)\npython smb_api.py smbk_xxx GET /leads --params '{\"positiveKeywords\":\"[\\\"*med*spa*\\\",\\\"*medical*spa*\\\",\\\"*aesthet*\\\",\\\"*botox*\\\",\\\"*medspa*\\\"]\",\"stateInclude\":\"FL\",\"limit\":\"25\"}'\n\n# Find auto shops in multiple states, exclude franchises\npython smb_api.py smbk_xxx GET /leads --params '{\"positiveKeywords\":\"[\\\"*auto*repair*\\\",\\\"*body*shop*\\\",\\\"*mechanic*\\\",\\\"*tire*\\\",\\\"*oil*change*\\\"]\",\"negativeKeywords\":\"[\\\"*franchise*\\\",\\\"*jiffy*\\\"]\",\"stateInclude\":\"GA,FL,NC,SC,TN\",\"limit\":\"50\"}'\n\n# Search for recently updated dental leads in Texas\npython smb_api.py smbk_xxx GET /leads --params '{\"positiveKeywords\":\"[\\\"*dental*\\\",\\\"*dentist*\\\",\\\"*orthodont*\\\",\\\"*oral*surg*\\\"]\",\"stateInclude\":\"TX\",\"lastUpdatedFrom\":\"rel:7d\"}'\n\n# Full-text search across all fields\npython smb_api.py smbk_xxx GET /leads --params '{\"search\":\"organic coffee\",\"limit\":\"25\"}'\n\n# Filter by website schema type (other database only)\npython smb_api.py smbk_xxx GET /leads --params '{\"websiteSchemaFilter\":\"LocalBusiness\",\"stateInclude\":\"CA\",\"limit\":\"25\"}'\n\n# Get available website schema types\npython smb_api.py smbk_xxx GET /leads/other/schema-types\n\n# Get account info (includes credit balance)\npython smb_api.py smbk_xxx GET /me\n\n# Export with credit controls\npython smb_api.py smbk_xxx POST /leads/export --body '{\"database\":\"other\",\"filters\":{\"positiveKeywords\":[\"*pet*groom*\",\"*veterinar*\",\"*dog*train*\"],\"stateInclude\":\"CA,OR,WA\"},\"maxCredits\":100}'\n\n# Export only previously-exported leads (free, no credits used)\npython smb_api.py smbk_xxx POST /leads/export --body '{\"database\":\"other\",\"filters\":{\"positiveKeywords\":[\"*dental*\"],\"stateInclude\":\"TX\"},\"maxCredits\":0}'\n\n# Purchase additional credits\npython smb_api.py smbk_xxx POST /purchase-credits --body '{\"creditCount\":500}'\n\n# Purchase credits by dollar amount\npython smb_api.py smbk_xxx POST /purchase-credits --body '{\"dollarAmount\":50}'\n\n# Change subscription plan\npython smb_api.py smbk_xxx POST /subscription/change-plan --body '{\"targetPlan\":\"growth\"}'\n\n# Cancel subscription\npython smb_api.py smbk_xxx POST /subscription/cancel\n\n# Start a programmatic purchase (no auth needed, but script still requires a placeholder key)\npython smb_api.py none POST /purchase --body '{\"email\":\"user@example.com\",\"plan\":\"starter\"}'\n\n# Claim API key after payment\npython smb_api.py none POST /claim-key --body '{\"email\":\"user@example.com\",\"claimToken\":\"tok_abc123\"}'\n\n# AI category suggestions\npython smb_api.py smbk_xxx POST /ai/suggest-categories --body '{\"companyName\":\"FitPro Supply\",\"companyDescription\":\"Commercial fitness equipment distributor\",\"productService\":\"Gym equipment, treadmills, weight systems\"}'\n\n# Create a filter preset\npython smb_api.py smbk_xxx POST /filter-presets --body '{\"name\":\"NY Bakeries\",\"filters\":{\"positiveKeywords\":[\"*bakery*\",\"*bake*shop*\",\"*cater*\",\"*pastry*\"],\"stateInclude\":\"NY\"}}'\n\n# Create email schedule with split distribution\npython smb_api.py smbk_xxx POST /email-schedules --body '{\"name\":\"Daily TX Leads\",\"filterPresetId\":5,\"intervalValue\":1,\"intervalUnit\":\"days\",\"recipients\":[\"rep1@co.com\",\"rep2@co.com\"],\"distributionMode\":\"split_evenly\",\"fullCopyRecipients\":[\"manager@co.com\"],\"maxLeadsPerEmail\":50}'\n\n# Enable AI auto-refine on a keyword list\npython smb_api.py smbk_xxx POST /ai/auto-refine/enable --body '{\"listId\":42}'\n\n# Check auto-refine status for a specific list\npython smb_api.py smbk_xxx GET /ai/auto-refine/status --params '{\"listId\":\"42\"}'\n\n# Check keyword generation job status\npython smb_api.py smbk_xxx GET /ai/keyword-status\n\n# Manually trigger an email schedule\npython smb_api.py smbk_xxx POST /email-schedules/15/trigger\n\n# Delete a filter preset\npython smb_api.py smbk_xxx DELETE /filter-presets/42\n\n\nThe script outputs JSON to stdout and rate limit headers to stderr. For export requests, files are automatically saved with sanitized filenames.\n\nRemember:\n\nUse multiple wildcard keyword variations to cast a wider net (e.g., [\"*dental*\", \"*dentist*\", \"*orthodont*\"] not just [\"dental\"]) — keywords are matched via OR logic\nUse * for flexible pattern matching: \"*auto*repair*\" matches \"auto body repair\", \"automotive repair shop\", etc.\nJSON array parameters should be serialized as strings inside the --params JSON\nAt least one positive filter is required for lead searches\nCheck which database the user needs before applying database-specific filters\nHome Improvement database provides phone numbers; Other database provides phone numbers and email addresses\nPhone and email are masked for free-tier users\nPresent results in a clean, readable table format\nFor credit-plan users, mention credits used/remaining after exports\nThe POST /purchase and POST /claim-key endpoints do not require authentication (no API key needed)\nSecurity\n\nThis skill addresses two specific agent execution risks: shell injection from constructing CLI commands with user input, and arbitrary file writes from unsanitized API-provided filenames.\n\nShell injection prevention: The smb_api.py script uses Python's requests library for all HTTP calls. User-provided search terms, locations, and other inputs are passed as structured function arguments — never interpolated into shell command strings. This eliminates the shell injection vector that exists when agents construct curl commands from user input.\n\nPath traversal prevention in exports: The /leads/export endpoint returns base64-encoded files with an API-provided fileName field. A malicious or corrupted filename (e.g., ../../etc/passwd) could write files to arbitrary locations. The script enforces three safeguards:\n\nBasename extraction: os.path.basename() strips all directory components — ../../etc/passwd becomes passwd\nExtension validation: Only .csv, .json, and .xlsx extensions are allowed; anything else defaults to .csv\nScoped output directory: Files are written only to the designated output directory (/mnt/user-data/outputs/ by default), never to user-specified or API-specified paths\n\nAPI key handling: The key is passed as a CLI argument and sent only in the Authorization header. It is never logged, written to files, or included in error output.\n\nError Handling\nStatus\tMeaning\n400\tBad request — check parameters\n401\tInvalid or missing API key\n402\tInsufficient credits (credit-plan users) — check credit balance with GET /me\n403\tActive subscription required\n404\tResource not found\n429\tRate limited — check Retry-After header\n500\tServer error\n\nAll errors return: { \"error\": \"error_code\", \"message\": \"Human-readable message\" }"
  },
  "trust": {
    "sourceLabel": "tencent",
    "provenanceUrl": "https://clawhub.ai/Tomsonx232/smb-sales-boost-leads",
    "publisherUrl": "https://clawhub.ai/Tomsonx232/smb-sales-boost-leads",
    "owner": "Tomsonx232",
    "version": "1.3.0",
    "license": null,
    "verificationStatus": "Indexed source record"
  },
  "links": {
    "detailUrl": "https://openagent3.xyz/skills/smb-sales-boost-leads",
    "downloadUrl": "https://openagent3.xyz/downloads/smb-sales-boost-leads",
    "agentUrl": "https://openagent3.xyz/skills/smb-sales-boost-leads/agent",
    "manifestUrl": "https://openagent3.xyz/skills/smb-sales-boost-leads/agent.json",
    "briefUrl": "https://openagent3.xyz/skills/smb-sales-boost-leads/agent.md"
  }
}