{
  "schemaVersion": "1.0",
  "item": {
    "slug": "ezyhost",
    "name": "EzyHost",
    "source": "tencent",
    "type": "skill",
    "category": "开发工具",
    "sourceUrl": "https://clawhub.ai/AraratDev/ezyhost",
    "canonicalUrl": "https://clawhub.ai/AraratDev/ezyhost",
    "targetPlatform": "OpenClaw"
  },
  "install": {
    "downloadMode": "redirect",
    "downloadUrl": "/downloads/ezyhost",
    "sourceDownloadUrl": "https://wry-manatee-359.convex.site/api/v1/download?slug=ezyhost",
    "sourcePlatform": "tencent",
    "targetPlatform": "OpenClaw",
    "installMethod": "Manual import",
    "extraction": "Extract archive",
    "prerequisites": [
      "OpenClaw"
    ],
    "packageFormat": "ZIP package",
    "includedAssets": [
      "skill.md"
    ],
    "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. 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. Summarize what changed and any follow-up checks I should run."
        }
      ]
    },
    "sourceHealth": {
      "source": "tencent",
      "status": "healthy",
      "reason": "direct_download_ok",
      "recommendedAction": "download",
      "checkedAt": "2026-04-30T16:55:25.780Z",
      "expiresAt": "2026-05-07T16:55:25.780Z",
      "httpStatus": 200,
      "finalUrl": "https://wry-manatee-359.convex.site/api/v1/download?slug=network",
      "contentType": "application/zip",
      "probeMethod": "head",
      "details": {
        "probeUrl": "https://wry-manatee-359.convex.site/api/v1/download?slug=network",
        "contentDisposition": "attachment; filename=\"network-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/ezyhost"
    },
    "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/ezyhost",
    "agentPageUrl": "https://openagent3.xyz/skills/ezyhost/agent",
    "manifestUrl": "https://openagent3.xyz/skills/ezyhost/agent.json",
    "briefUrl": "https://openagent3.xyz/skills/ezyhost/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. 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. Summarize what changed and any follow-up checks I should run."
      }
    ]
  },
  "documentation": {
    "source": "clawhub",
    "primaryDoc": "SKILL.md",
    "sections": [
      {
        "title": "EzyHost — Agent Skill",
        "body": "This document describes how AI agents can interact with EzyHost programmatically.\nFor human users, visit ezyhost.io."
      },
      {
        "title": "Base URL",
        "body": "https://ezyhost.io/api"
      },
      {
        "title": "Authentication",
        "body": "All API requests require an API key passed as a header:\n\nx-api-key: $EZYHOST_API_KEY\n\nThe key is loaded from the EZYHOST_API_KEY environment variable. Generate your API key at https://ezyhost.io/dashboard/api-keys.\n\nNote: API access requires the Pro plan or higher."
      },
      {
        "title": "Projects",
        "body": "List Projects\n\nGET /api/projects\n\nReturns { projects: [{ id, name, slug, subdomain, customDomain, status, storageUsed, seoScore, deployedAt, _count: { files, analytics } }] }\n\nCreate Project\n\nPOST /api/projects\nContent-Type: application/json\nBody: { \"name\": \"my-site\", \"subdomain\": \"my-site\" }\n\nReturns { project: { id, name, subdomain, s3Prefix, url, ... } }\n\nThe subdomain must be 3+ characters, lowercase alphanumeric with hyphens. Returns 409 SUBDOMAIN_TAKEN if already in use. Your site will be live at https://{subdomain}.ezyhost.site.\n\nOptional fields: displayMode (\"standard\" | \"presentation\"), hideFromSearch (boolean), password (string).\n\nCheck Subdomain Availability\n\nGET /api/projects/check-subdomain/:subdomain\n\nReturns { available: true/false, subdomain }. Use this to validate before creating.\n\nGet Project\n\nGET /api/projects/:id\n\nReturns { project: { id, name, subdomain, customDomain, status, storageUsed, seoScore, files: [...], ... } }\n\nUpdate Project\n\nPATCH /api/projects/:id\nContent-Type: application/json\nBody: { \"name\": \"new-name\", \"metaTitle\": \"...\", \"metaDescription\": \"...\", \"password\": \"...\", \"removeBranding\": true, \"displayMode\": \"standard\", \"hideFromSearch\": false, \"emailCapture\": true }\n\nDelete Project\n\nDELETE /api/projects/:id\n\nDeletes the project and all associated files from storage. This cannot be undone."
      },
      {
        "title": "File Upload",
        "body": "Upload Files (ZIP or individual)\n\nPOST /api/upload/:projectId\nContent-Type: multipart/form-data\nBody: files (multipart)\n\nReturns { message, filesUploaded, totalSize, project: { id, subdomain } }\n\nSupports .zip archives (auto-extracted) and individual files. All uploaded files go through malware scanning (ClamAV + magic byte validation).\n\nSupported file types: HTML, CSS, JS, JSON, XML, SVG, images (PNG, JPG, GIF, WebP, AVIF, ICO), PDFs, presentations (PPTX), documents (DOCX, XLSX), audio (MP3, WAV, OGG, FLAC, AAC), video (MP4, WebM, MOV), fonts (WOFF, WOFF2, TTF, OTF, EOT), archives (ZIP), 3D models (GLB, GLTF, OBJ), and any other static asset.\n\nBlocked file types: Executables (.exe, .dll, .bat, .sh, .php, .asp, .jar) and SVGs containing scripts or event handlers are rejected.\n\nDelete a File\n\nDELETE /api/upload/:projectId/files/:fileId\n\nBulk Delete Files\n\nPOST /api/upload/:projectId/files/bulk-delete\nContent-Type: application/json\nBody: { \"fileIds\": [\"id1\", \"id2\", \"id3\"] }\n\nRename a File\n\nPATCH /api/upload/:projectId/files/:fileId\nContent-Type: application/json\nBody: { \"newPath\": \"assets/renamed-file.png\" }"
      },
      {
        "title": "GitHub Import",
        "body": "Import from GitHub\n\nPOST /api/github/:projectId\nContent-Type: application/json\nBody: { \"owner\": \"username\", \"repo\": \"repo-name\", \"branch\": \"main\", \"subfolder\": \"dist\" }\n\nReturns { message, repo, branch, filesUploaded, filesSkipped, totalSize }\n\nImports files from a public GitHub repository. The branch defaults to \"main\" and automatically falls back to \"master\" if not found. The optional subfolder field lets you import only a subdirectory (e.g. \"dist\", \"build\").\n\nRequires Pro plan or higher."
      },
      {
        "title": "Version Rollback",
        "body": "List Versions\n\nGET /api/versions/:projectId\n\nReturns { versions: [{ id, version, label, fileCount, totalSize, createdAt }] }\n\nCreate Version Snapshot\n\nPOST /api/versions/:projectId\nContent-Type: application/json\nBody: { \"label\": \"v1.0\" }\n\nSnapshots the current state of all project files. Requires Pro plan or higher.\n\nRollback to Version\n\nPOST /api/versions/:projectId/rollback/:version\n\nRestores all files to the state captured in the specified version number."
      },
      {
        "title": "SEO",
        "body": "Get SEO Report\n\nGET /api/seo/:projectId\n\nReturns { score, suggestions: [{ id, type, severity, message, resolved }] }\n\nRequires Pro plan or higher.\n\nRun SEO Analysis\n\nPOST /api/seo/:projectId/analyze\n\nTriggers a fresh SEO scan and returns updated suggestions.\n\nResolve a Suggestion\n\nPATCH /api/seo/suggestion/:id/resolve\n\nAI Auto-Fix SEO Issues\n\nPOST /api/seo/:projectId/ai-fix\nContent-Type: application/json\nBody: { \"suggestionIds\": [\"id1\", \"id2\"] }\n\nUses AI to automatically fix SEO issues in your HTML files. Counts against AI generation limits."
      },
      {
        "title": "Analytics",
        "body": "Get Analytics\n\nGET /api/analytics/:projectId?period=7d\n\nPeriods: 24h, 7d, 30d, 90d\n\nBasic analytics (all plans):\nReturns { totalVisits, visitsByDay, topPages, isAdvanced }\n\nAdvanced analytics (Pro+ plans):\nAdditionally returns { uniqueVisitors, uniqueByDay, topReferrers, topCountries, devices, browsers }\n\nFree plan users receive isAdvanced: false and advanced fields are empty.\n\nTrack Event (public, no auth required)\n\nPOST /api/analytics/track\nContent-Type: application/json\nBody: { \"projectId\": \"...\", \"path\": \"/page\", \"referrer\": \"...\" }"
      },
      {
        "title": "QR Codes",
        "body": "Generate QR Code\n\nPOST /api/qrcode/:projectId\n\nReturns { qrCodeUrl: \"data:image/png;base64,...\", siteUrl: \"https://...\" }\n\nGenerates a QR code pointing to the project's live URL (subdomain or custom domain). Returns a base64 data URL. Available on all paid plans.\n\nGet QR Code\n\nGET /api/qrcode/:projectId\n\nReturns { qrCodeUrl: \"data:image/...\" | null }"
      },
      {
        "title": "Email Capture",
        "body": "Toggle Email Capture on Project\n\nPATCH /api/emails/:projectId/toggle\n\nReturns { emailCapture: true/false }. Requires Business plan.\n\nWhen enabled, visitors to the hosted site see a popup email collection form after 5 seconds.\n\nSubmit Email (public, no auth)\n\nPOST /api/emails/submit\nContent-Type: application/json\nBody: { \"email\": \"visitor@example.com\", \"projectId\": \"...\", \"source\": \"modal\" }\n\nSource options: modal, inline, api. Only works if the project has email capture enabled and the project owner has a Business plan.\n\nGet Captured Emails\n\nGET /api/emails/:projectId?page=1&limit=50\n\nReturns { emails: [{ id, email, source, createdAt }], total, page, totalPages }\n\nRequires Business plan.\n\nExport Emails as CSV\n\nGET /api/emails/:projectId/export\n\nReturns a CSV file download. Requires Business plan.\n\nDelete a Captured Email\n\nDELETE /api/emails/:projectId/:emailId"
      },
      {
        "title": "Teams",
        "body": "List Teams\n\nGET /api/teams\n\nReturns { teams: [{ id, name, ownerId, members: [...] }] }\n\nCreate Team\n\nPOST /api/teams\nContent-Type: application/json\nBody: { \"name\": \"My Team\" }\n\nRequires Business plan.\n\nAdd Team Member\n\nPOST /api/teams/:teamId/members\nContent-Type: application/json\nBody: { \"email\": \"user@example.com\", \"role\": \"editor\" }\n\nRoles: editor, viewer.\n\nUpdate Member Role\n\nPATCH /api/teams/:teamId/members/:memberId\nContent-Type: application/json\nBody: { \"role\": \"viewer\" }\n\nRemove Team Member\n\nDELETE /api/teams/:teamId/members/:memberId\n\nLeave Team\n\nPOST /api/teams/:teamId/leave\n\nDelete Team\n\nDELETE /api/teams/:teamId"
      },
      {
        "title": "Domains",
        "body": "Add Custom Domain\n\nPOST /api/domains/:projectId\nContent-Type: application/json\nBody: { \"domain\": \"example.com\" }\n\nReturns { dnsInstructions: { type, name, value } } — DNS records you need to create.\n\nRequires Pro plan or higher.\n\nVerify Domain DNS\n\nGET /api/domains/:projectId/verify\n\nReturns { verified: true/false, dnsInstructions }. Call this after setting up DNS records.\n\nRemove Domain\n\nDELETE /api/domains/:projectId"
      },
      {
        "title": "AI Builder",
        "body": "Chat (generate/edit websites via AI)\n\nPOST /api/aibuilder/chat\nContent-Type: application/json\nBody: { \"message\": \"build a portfolio site\", \"history\": [], \"currentFiles\": [] }\n\nReturns SSE stream with events:\n\nstatus — progress updates (\"Generating HTML...\")\nprogress — percentage (0-100)\ndone — { files: [{ filename, content }] } — the generated files\nerror — { message } on failure\n\nCounts against per-plan AI generation limits. Only one AI generation can run at a time per user.\n\nDeploy AI-Generated Files\n\nPOST /api/aibuilder/deploy/:projectId\nContent-Type: application/json\nBody: { \"files\": [{ \"filename\": \"index.html\", \"content\": \"<!DOCTYPE html>...\" }] }\n\nDownload as ZIP\n\nPOST /api/aibuilder/download-zip\nContent-Type: application/json\nBody: { \"files\": [{ \"filename\": \"index.html\", \"content\": \"...\" }] }\n\nReturns a ZIP file download.\n\nTemplates\n\nGET    /api/aibuilder/templates           — list saved templates\nGET    /api/aibuilder/templates/:id       — get template details\nPOST   /api/aibuilder/templates           — save new template\nPATCH  /api/aibuilder/templates/:id       — update template\nDELETE /api/aibuilder/templates/:id       — delete template\n\nTemplate body: { \"name\": \"My Template\", \"description\": \"...\", \"messages\": [...], \"files\": [...] }"
      },
      {
        "title": "API Keys",
        "body": "Get Current Key\n\nGET /api/apikey\n\nReturns { hasKey: true/false, apiKey: \"ag_••••...\" } — key is partially masked.\n\nGenerate New Key\n\nPOST /api/apikey/generate\n\nReturns { apiKey: \"ag_...\" } — full key shown only once. Store it securely. Revokes any previous key.\n\nRequires Pro plan or higher.\n\nRevoke Key\n\nDELETE /api/apikey"
      },
      {
        "title": "Plans (Public)",
        "body": "Get All Plans\n\nGET /api/plans\n\nNo authentication required. Returns { plans: [{ plan, name, priceMonthly, maxProjects, maxStorageMB, ... }] } with all feature flags and limits for each plan."
      },
      {
        "title": "Billing",
        "body": "Get Billing Info\n\nGET /api/billing\n\nReturns { plan, subscription, aiCredits, usage }.\n\nGet AI Usage\n\nGET /api/billing/ai-usage\n\nReturns { used, limit, remaining, resetsAt }."
      },
      {
        "title": "Plan Limits",
        "body": "FeatureFreePro ($9/mo)Business ($29/mo)Projects215UnlimitedStorage50 MB2 GB20 GBMax file size10 MB100 MB500 MBCustom domains—3UnlimitedAPI access—✅✅GitHub import—✅✅Version rollback—Up to 5Up to 30Password protection—✅✅Remove branding—✅✅SEO tools—✅✅Advanced analytics—✅✅QR codes✅✅✅Hide from search—✅✅Email capture——✅Team members——Up to 5Priority support——✅AI generations3/mo10/mo30/moAI templates110UnlimitedPresentation mode—✅✅Basic analytics✅✅✅"
      },
      {
        "title": "Hosted Site URLs",
        "body": "Sites are served at:\n\nFree subdomain: https://{subdomain}.ezyhost.site\nCustom domain: https://{your-domain.com} (Pro+ plans)\n\nAll sites include HTTPS, CDN caching, automatic file browser for non-HTML projects, and optional presentation mode for PDF/PPTX files.\n\nInjected features on served sites:\n\nBranding badge: \"Hosted on ezyhost\" badge shown on free plan sites. Removable on paid plans via removeBranding project setting.\nEmail capture popup: When enabled (Business plan), visitors see a subscribe popup after 5 seconds. Dismissible and stored in sessionStorage.\nAnalytics tracking: Pageviews are automatically tracked for HTML files."
      },
      {
        "title": "Error Responses",
        "body": "All errors return JSON:\n\n{ \"error\": \"Description of the error\" }\n\nPlan limit errors include \"upgrade\": true to indicate a higher plan is needed:\n\n{ \"error\": \"GitHub import requires a Pro plan or higher\", \"upgrade\": true }\n\nSubdomain conflicts:\n\n{ \"error\": \"The subdomain \\\"my-site\\\" is already taken.\", \"code\": \"SUBDOMAIN_TAKEN\" }\n\nCommon HTTP status codes:\n\n400 — Bad request / validation error\n401 — Not authenticated\n403 — Plan limit reached or feature disabled\n404 — Resource not found\n409 — Conflict (subdomain taken)\n429 — Rate limited\n500 — Server error"
      },
      {
        "title": "Rate Limits",
        "body": "General API: 300 requests per 15 minutes per API key\nUpload: 2 requests per second\nAnalytics tracking: 60 writes per minute per IP\nEmail capture submit: 10 per minute per IP\nAI Builder: Subject to per-plan generation limits (1 concurrent request max)"
      },
      {
        "title": "Example: Deploy a Static Site",
        "body": "# 1. Check subdomain availability\ncurl https://ezyhost.io/api/projects/check-subdomain/my-site \\\n  -H \"x-api-key: $EZYHOST_API_KEY\"\n\n# 2. Create a project\ncurl -X POST https://ezyhost.io/api/projects \\\n  -H \"x-api-key: $EZYHOST_API_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"name\": \"my-site\", \"subdomain\": \"my-site\"}'\n\n# 3. Upload files (ZIP)\ncurl -X POST https://ezyhost.io/api/upload/PROJECT_ID \\\n  -H \"x-api-key: $EZYHOST_API_KEY\" \\\n  -F \"files=@site.zip\"\n\n# 4. Generate QR code\ncurl -X POST https://ezyhost.io/api/qrcode/PROJECT_ID \\\n  -H \"x-api-key: $EZYHOST_API_KEY\"\n\n# 5. Check SEO (Pro+)\ncurl https://ezyhost.io/api/seo/PROJECT_ID \\\n  -H \"x-api-key: $EZYHOST_API_KEY\"\n\n# 6. Add custom domain (Pro+)\ncurl -X POST https://ezyhost.io/api/domains/PROJECT_ID \\\n  -H \"x-api-key: $EZYHOST_API_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"domain\": \"example.com\"}'\n\nYour site is now live at https://my-site.ezyhost.site"
      },
      {
        "title": "Example: Import from GitHub",
        "body": "# Import a public repo (auto-detects main/master branch)\ncurl -X POST https://ezyhost.io/api/github/PROJECT_ID \\\n  -H \"x-api-key: $EZYHOST_API_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"owner\": \"emilbaehr\", \"repo\": \"automatic-app-landing-page\"}'"
      },
      {
        "title": "Example: AI-Generate and Deploy",
        "body": "# 1. Generate a site with AI (SSE stream)\ncurl -N -X POST https://ezyhost.io/api/aibuilder/chat \\\n  -H \"x-api-key: $EZYHOST_API_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"message\": \"build a modern portfolio with dark theme\", \"history\": []}'\n\n# 2. Deploy the generated files to a project\ncurl -X POST https://ezyhost.io/api/aibuilder/deploy/PROJECT_ID \\\n  -H \"x-api-key: $EZYHOST_API_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"files\": [{\"filename\": \"index.html\", \"content\": \"...\"}]}'"
      }
    ],
    "body": "EzyHost — Agent Skill\n\nThis document describes how AI agents can interact with EzyHost programmatically. For human users, visit ezyhost.io.\n\nBase URL\nhttps://ezyhost.io/api\n\nAuthentication\n\nAll API requests require an API key passed as a header:\n\nx-api-key: $EZYHOST_API_KEY\n\n\nThe key is loaded from the EZYHOST_API_KEY environment variable. Generate your API key at https://ezyhost.io/dashboard/api-keys.\n\nNote: API access requires the Pro plan or higher.\n\nEndpoints\nProjects\nList Projects\nGET /api/projects\n\n\nReturns { projects: [{ id, name, slug, subdomain, customDomain, status, storageUsed, seoScore, deployedAt, _count: { files, analytics } }] }\n\nCreate Project\nPOST /api/projects\nContent-Type: application/json\nBody: { \"name\": \"my-site\", \"subdomain\": \"my-site\" }\n\n\nReturns { project: { id, name, subdomain, s3Prefix, url, ... } }\n\nThe subdomain must be 3+ characters, lowercase alphanumeric with hyphens. Returns 409 SUBDOMAIN_TAKEN if already in use. Your site will be live at https://{subdomain}.ezyhost.site.\n\nOptional fields: displayMode (\"standard\" | \"presentation\"), hideFromSearch (boolean), password (string).\n\nCheck Subdomain Availability\nGET /api/projects/check-subdomain/:subdomain\n\n\nReturns { available: true/false, subdomain }. Use this to validate before creating.\n\nGet Project\nGET /api/projects/:id\n\n\nReturns { project: { id, name, subdomain, customDomain, status, storageUsed, seoScore, files: [...], ... } }\n\nUpdate Project\nPATCH /api/projects/:id\nContent-Type: application/json\nBody: { \"name\": \"new-name\", \"metaTitle\": \"...\", \"metaDescription\": \"...\", \"password\": \"...\", \"removeBranding\": true, \"displayMode\": \"standard\", \"hideFromSearch\": false, \"emailCapture\": true }\n\nDelete Project\nDELETE /api/projects/:id\n\n\nDeletes the project and all associated files from storage. This cannot be undone.\n\nFile Upload\nUpload Files (ZIP or individual)\nPOST /api/upload/:projectId\nContent-Type: multipart/form-data\nBody: files (multipart)\n\n\nReturns { message, filesUploaded, totalSize, project: { id, subdomain } }\n\nSupports .zip archives (auto-extracted) and individual files. All uploaded files go through malware scanning (ClamAV + magic byte validation).\n\nSupported file types: HTML, CSS, JS, JSON, XML, SVG, images (PNG, JPG, GIF, WebP, AVIF, ICO), PDFs, presentations (PPTX), documents (DOCX, XLSX), audio (MP3, WAV, OGG, FLAC, AAC), video (MP4, WebM, MOV), fonts (WOFF, WOFF2, TTF, OTF, EOT), archives (ZIP), 3D models (GLB, GLTF, OBJ), and any other static asset.\n\nBlocked file types: Executables (.exe, .dll, .bat, .sh, .php, .asp, .jar) and SVGs containing scripts or event handlers are rejected.\n\nDelete a File\nDELETE /api/upload/:projectId/files/:fileId\n\nBulk Delete Files\nPOST /api/upload/:projectId/files/bulk-delete\nContent-Type: application/json\nBody: { \"fileIds\": [\"id1\", \"id2\", \"id3\"] }\n\nRename a File\nPATCH /api/upload/:projectId/files/:fileId\nContent-Type: application/json\nBody: { \"newPath\": \"assets/renamed-file.png\" }\n\nGitHub Import\nImport from GitHub\nPOST /api/github/:projectId\nContent-Type: application/json\nBody: { \"owner\": \"username\", \"repo\": \"repo-name\", \"branch\": \"main\", \"subfolder\": \"dist\" }\n\n\nReturns { message, repo, branch, filesUploaded, filesSkipped, totalSize }\n\nImports files from a public GitHub repository. The branch defaults to \"main\" and automatically falls back to \"master\" if not found. The optional subfolder field lets you import only a subdirectory (e.g. \"dist\", \"build\").\n\nRequires Pro plan or higher.\n\nVersion Rollback\nList Versions\nGET /api/versions/:projectId\n\n\nReturns { versions: [{ id, version, label, fileCount, totalSize, createdAt }] }\n\nCreate Version Snapshot\nPOST /api/versions/:projectId\nContent-Type: application/json\nBody: { \"label\": \"v1.0\" }\n\n\nSnapshots the current state of all project files. Requires Pro plan or higher.\n\nRollback to Version\nPOST /api/versions/:projectId/rollback/:version\n\n\nRestores all files to the state captured in the specified version number.\n\nSEO\nGet SEO Report\nGET /api/seo/:projectId\n\n\nReturns { score, suggestions: [{ id, type, severity, message, resolved }] }\n\nRequires Pro plan or higher.\n\nRun SEO Analysis\nPOST /api/seo/:projectId/analyze\n\n\nTriggers a fresh SEO scan and returns updated suggestions.\n\nResolve a Suggestion\nPATCH /api/seo/suggestion/:id/resolve\n\nAI Auto-Fix SEO Issues\nPOST /api/seo/:projectId/ai-fix\nContent-Type: application/json\nBody: { \"suggestionIds\": [\"id1\", \"id2\"] }\n\n\nUses AI to automatically fix SEO issues in your HTML files. Counts against AI generation limits.\n\nAnalytics\nGet Analytics\nGET /api/analytics/:projectId?period=7d\n\n\nPeriods: 24h, 7d, 30d, 90d\n\nBasic analytics (all plans): Returns { totalVisits, visitsByDay, topPages, isAdvanced }\n\nAdvanced analytics (Pro+ plans): Additionally returns { uniqueVisitors, uniqueByDay, topReferrers, topCountries, devices, browsers }\n\nFree plan users receive isAdvanced: false and advanced fields are empty.\n\nTrack Event (public, no auth required)\nPOST /api/analytics/track\nContent-Type: application/json\nBody: { \"projectId\": \"...\", \"path\": \"/page\", \"referrer\": \"...\" }\n\nQR Codes\nGenerate QR Code\nPOST /api/qrcode/:projectId\n\n\nReturns { qrCodeUrl: \"data:image/png;base64,...\", siteUrl: \"https://...\" }\n\nGenerates a QR code pointing to the project's live URL (subdomain or custom domain). Returns a base64 data URL. Available on all paid plans.\n\nGet QR Code\nGET /api/qrcode/:projectId\n\n\nReturns { qrCodeUrl: \"data:image/...\" | null }\n\nEmail Capture\nToggle Email Capture on Project\nPATCH /api/emails/:projectId/toggle\n\n\nReturns { emailCapture: true/false }. Requires Business plan.\n\nWhen enabled, visitors to the hosted site see a popup email collection form after 5 seconds.\n\nSubmit Email (public, no auth)\nPOST /api/emails/submit\nContent-Type: application/json\nBody: { \"email\": \"visitor@example.com\", \"projectId\": \"...\", \"source\": \"modal\" }\n\n\nSource options: modal, inline, api. Only works if the project has email capture enabled and the project owner has a Business plan.\n\nGet Captured Emails\nGET /api/emails/:projectId?page=1&limit=50\n\n\nReturns { emails: [{ id, email, source, createdAt }], total, page, totalPages }\n\nRequires Business plan.\n\nExport Emails as CSV\nGET /api/emails/:projectId/export\n\n\nReturns a CSV file download. Requires Business plan.\n\nDelete a Captured Email\nDELETE /api/emails/:projectId/:emailId\n\nTeams\nList Teams\nGET /api/teams\n\n\nReturns { teams: [{ id, name, ownerId, members: [...] }] }\n\nCreate Team\nPOST /api/teams\nContent-Type: application/json\nBody: { \"name\": \"My Team\" }\n\n\nRequires Business plan.\n\nAdd Team Member\nPOST /api/teams/:teamId/members\nContent-Type: application/json\nBody: { \"email\": \"user@example.com\", \"role\": \"editor\" }\n\n\nRoles: editor, viewer.\n\nUpdate Member Role\nPATCH /api/teams/:teamId/members/:memberId\nContent-Type: application/json\nBody: { \"role\": \"viewer\" }\n\nRemove Team Member\nDELETE /api/teams/:teamId/members/:memberId\n\nLeave Team\nPOST /api/teams/:teamId/leave\n\nDelete Team\nDELETE /api/teams/:teamId\n\nDomains\nAdd Custom Domain\nPOST /api/domains/:projectId\nContent-Type: application/json\nBody: { \"domain\": \"example.com\" }\n\n\nReturns { dnsInstructions: { type, name, value } } — DNS records you need to create.\n\nRequires Pro plan or higher.\n\nVerify Domain DNS\nGET /api/domains/:projectId/verify\n\n\nReturns { verified: true/false, dnsInstructions }. Call this after setting up DNS records.\n\nRemove Domain\nDELETE /api/domains/:projectId\n\nAI Builder\nChat (generate/edit websites via AI)\nPOST /api/aibuilder/chat\nContent-Type: application/json\nBody: { \"message\": \"build a portfolio site\", \"history\": [], \"currentFiles\": [] }\n\n\nReturns SSE stream with events:\n\nstatus — progress updates (\"Generating HTML...\")\nprogress — percentage (0-100)\ndone — { files: [{ filename, content }] } — the generated files\nerror — { message } on failure\n\nCounts against per-plan AI generation limits. Only one AI generation can run at a time per user.\n\nDeploy AI-Generated Files\nPOST /api/aibuilder/deploy/:projectId\nContent-Type: application/json\nBody: { \"files\": [{ \"filename\": \"index.html\", \"content\": \"<!DOCTYPE html>...\" }] }\n\nDownload as ZIP\nPOST /api/aibuilder/download-zip\nContent-Type: application/json\nBody: { \"files\": [{ \"filename\": \"index.html\", \"content\": \"...\" }] }\n\n\nReturns a ZIP file download.\n\nTemplates\nGET    /api/aibuilder/templates           — list saved templates\nGET    /api/aibuilder/templates/:id       — get template details\nPOST   /api/aibuilder/templates           — save new template\nPATCH  /api/aibuilder/templates/:id       — update template\nDELETE /api/aibuilder/templates/:id       — delete template\n\n\nTemplate body: { \"name\": \"My Template\", \"description\": \"...\", \"messages\": [...], \"files\": [...] }\n\nAPI Keys\nGet Current Key\nGET /api/apikey\n\n\nReturns { hasKey: true/false, apiKey: \"ag_••••...\" } — key is partially masked.\n\nGenerate New Key\nPOST /api/apikey/generate\n\n\nReturns { apiKey: \"ag_...\" } — full key shown only once. Store it securely. Revokes any previous key.\n\nRequires Pro plan or higher.\n\nRevoke Key\nDELETE /api/apikey\n\nPlans (Public)\nGet All Plans\nGET /api/plans\n\n\nNo authentication required. Returns { plans: [{ plan, name, priceMonthly, maxProjects, maxStorageMB, ... }] } with all feature flags and limits for each plan.\n\nBilling\nGet Billing Info\nGET /api/billing\n\n\nReturns { plan, subscription, aiCredits, usage }.\n\nGet AI Usage\nGET /api/billing/ai-usage\n\n\nReturns { used, limit, remaining, resetsAt }.\n\nPlan Limits\nFeature\tFree\tPro ($9/mo)\tBusiness ($29/mo)\nProjects\t2\t15\tUnlimited\nStorage\t50 MB\t2 GB\t20 GB\nMax file size\t10 MB\t100 MB\t500 MB\nCustom domains\t—\t3\tUnlimited\nAPI access\t—\t✅\t✅\nGitHub import\t—\t✅\t✅\nVersion rollback\t—\tUp to 5\tUp to 30\nPassword protection\t—\t✅\t✅\nRemove branding\t—\t✅\t✅\nSEO tools\t—\t✅\t✅\nAdvanced analytics\t—\t✅\t✅\nQR codes\t✅\t✅\t✅\nHide from search\t—\t✅\t✅\nEmail capture\t—\t—\t✅\nTeam members\t—\t—\tUp to 5\nPriority support\t—\t—\t✅\nAI generations\t3/mo\t10/mo\t30/mo\nAI templates\t1\t10\tUnlimited\nPresentation mode\t—\t✅\t✅\nBasic analytics\t✅\t✅\t✅\nHosted Site URLs\n\nSites are served at:\n\nFree subdomain: https://{subdomain}.ezyhost.site\nCustom domain: https://{your-domain.com} (Pro+ plans)\n\nAll sites include HTTPS, CDN caching, automatic file browser for non-HTML projects, and optional presentation mode for PDF/PPTX files.\n\nInjected features on served sites:\n\nBranding badge: \"Hosted on ezyhost\" badge shown on free plan sites. Removable on paid plans via removeBranding project setting.\nEmail capture popup: When enabled (Business plan), visitors see a subscribe popup after 5 seconds. Dismissible and stored in sessionStorage.\nAnalytics tracking: Pageviews are automatically tracked for HTML files.\nError Responses\n\nAll errors return JSON:\n\n{ \"error\": \"Description of the error\" }\n\n\nPlan limit errors include \"upgrade\": true to indicate a higher plan is needed:\n\n{ \"error\": \"GitHub import requires a Pro plan or higher\", \"upgrade\": true }\n\n\nSubdomain conflicts:\n\n{ \"error\": \"The subdomain \\\"my-site\\\" is already taken.\", \"code\": \"SUBDOMAIN_TAKEN\" }\n\n\nCommon HTTP status codes:\n\n400 — Bad request / validation error\n401 — Not authenticated\n403 — Plan limit reached or feature disabled\n404 — Resource not found\n409 — Conflict (subdomain taken)\n429 — Rate limited\n500 — Server error\nRate Limits\nGeneral API: 300 requests per 15 minutes per API key\nUpload: 2 requests per second\nAnalytics tracking: 60 writes per minute per IP\nEmail capture submit: 10 per minute per IP\nAI Builder: Subject to per-plan generation limits (1 concurrent request max)\nExample: Deploy a Static Site\n# 1. Check subdomain availability\ncurl https://ezyhost.io/api/projects/check-subdomain/my-site \\\n  -H \"x-api-key: $EZYHOST_API_KEY\"\n\n# 2. Create a project\ncurl -X POST https://ezyhost.io/api/projects \\\n  -H \"x-api-key: $EZYHOST_API_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"name\": \"my-site\", \"subdomain\": \"my-site\"}'\n\n# 3. Upload files (ZIP)\ncurl -X POST https://ezyhost.io/api/upload/PROJECT_ID \\\n  -H \"x-api-key: $EZYHOST_API_KEY\" \\\n  -F \"files=@site.zip\"\n\n# 4. Generate QR code\ncurl -X POST https://ezyhost.io/api/qrcode/PROJECT_ID \\\n  -H \"x-api-key: $EZYHOST_API_KEY\"\n\n# 5. Check SEO (Pro+)\ncurl https://ezyhost.io/api/seo/PROJECT_ID \\\n  -H \"x-api-key: $EZYHOST_API_KEY\"\n\n# 6. Add custom domain (Pro+)\ncurl -X POST https://ezyhost.io/api/domains/PROJECT_ID \\\n  -H \"x-api-key: $EZYHOST_API_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"domain\": \"example.com\"}'\n\n\nYour site is now live at https://my-site.ezyhost.site\n\nExample: Import from GitHub\n# Import a public repo (auto-detects main/master branch)\ncurl -X POST https://ezyhost.io/api/github/PROJECT_ID \\\n  -H \"x-api-key: $EZYHOST_API_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"owner\": \"emilbaehr\", \"repo\": \"automatic-app-landing-page\"}'\n\nExample: AI-Generate and Deploy\n# 1. Generate a site with AI (SSE stream)\ncurl -N -X POST https://ezyhost.io/api/aibuilder/chat \\\n  -H \"x-api-key: $EZYHOST_API_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"message\": \"build a modern portfolio with dark theme\", \"history\": []}'\n\n# 2. Deploy the generated files to a project\ncurl -X POST https://ezyhost.io/api/aibuilder/deploy/PROJECT_ID \\\n  -H \"x-api-key: $EZYHOST_API_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"files\": [{\"filename\": \"index.html\", \"content\": \"...\"}]}'"
  },
  "trust": {
    "sourceLabel": "tencent",
    "provenanceUrl": "https://clawhub.ai/AraratDev/ezyhost",
    "publisherUrl": "https://clawhub.ai/AraratDev/ezyhost",
    "owner": "AraratDev",
    "version": "1.0.3",
    "license": null,
    "verificationStatus": "Indexed source record"
  },
  "links": {
    "detailUrl": "https://openagent3.xyz/skills/ezyhost",
    "downloadUrl": "https://openagent3.xyz/downloads/ezyhost",
    "agentUrl": "https://openagent3.xyz/skills/ezyhost/agent",
    "manifestUrl": "https://openagent3.xyz/skills/ezyhost/agent.json",
    "briefUrl": "https://openagent3.xyz/skills/ezyhost/agent.md"
  }
}