# htmlshare publisher API instructions htmlshare publishes generated HTML/CSS/JS bundles and returns URLs that humans can open. This deployment is account-controlled: publishing requires a confirmed publisher account or an `hsk_...` API key. Production base URL: ```text https://share.ecija.ai ``` Use htmlshare when an assistant has generated an HTML report, explanation, prototype, market scan, or other static artifact and an authorized publisher wants to share it. ## Default: registered publish ```http POST https://share.ecija.ai/api/v1/publish Authorization: Bearer hsk_... Content-Type: application/json { "mode": "registered", "title": "My report", "folder": "my-report", "visibility": "recipients", "share": { "emails": ["reader@example.com", "@example.com"] }, "files": { "index.html": "

My report

" } } ``` Copy-ready curl example: ```bash curl -X POST https://share.ecija.ai/api/v1/publish \ -H 'authorization: Bearer hsk_...' \ -H 'content-type: application/json' \ --data '{"mode":"registered","title":"My report","folder":"my-report","visibility":"recipients","share":{"emails":["reader@example.com","@example.com"]},"files":{"index.html":"

My report

"}}' ``` Optional `folder` sets the public URL folder: `/f/my-report/`. It is normalized to URL-safe lowercase letters, numbers, and dashes. The publish request fails with `409 Conflict` if the folder already exists. `slug` is accepted as an alias for `folder`. ## Updating an existing publication Use the MCP tool `configure_html` to change settings without replacing files: ```json { "publication_id_or_slug": "my-report", "title": "Updated report title", "visibility": "recipients", "require_registration": true, "emails": ["reader@example.com", "@example.com"] } ``` Valid visibility values are `private`, `company`, `recipients`, `signed`, and `public`. `emails` or `share.emails` add recipient/domain targets; signed visibility requires specific email addresses, not domain targets. Use `unpublish_html` to remove a publication from shared/public access without deleting its files: ```json { "publication_id_or_slug": "my-report", "revoke_access": true } ``` `unpublish_html` sets visibility to `private` and requires registration. By default it removes recipient/domain shares, pending magic links, and signed access tokens while retaining signed audit proofs. Use `delete_html` only when the publication and its files must be permanently deleted: ```json { "publication_id_or_slug": "my-report", "confirm_delete": true } ``` Use the MCP tool `update_html` to update an owned publication. Identify it with `publication_id_or_slug`, `id`, or `slug`. ```json { "publication_id_or_slug": "my-report", "title": "Updated report", "visibility": "company", "files": { "index.html": "

Updated

", "assets/app.js": "console.log('updated')" }, "delete_files": ["assets/old.js"] } ``` Files listed in `files` are added or replaced. To replace the main document, upload a new `index.html`. `delete_files` can remove secondary files, but `index.html` cannot be deleted; replace it instead. ## Publishing a React/Vite build You can publish a React app when it is compiled to static files. Build locally first: ```bash npm run build ``` Then publish the generated `dist/` contents, including `index.html` and referenced `assets/*.js` and `assets/*.css` files, as entries in the `files` object. For Vite apps, prefer relative asset paths so the app works under the htmlshare publication URL (`/f//`): ```ts // vite.config.ts export default defineConfig({ base: "./", }); ``` If the app uses client-side routing, prefer hash routing (`HashRouter`) instead of browser history routing. Direct paths such as `/dashboard` may not reload correctly inside a static htmlshare publication, while `/#/dashboard` will. Current upload support is text-oriented (`html`, `css`, `js`, `json`, `svg`, `txt`, `md`, etc.). If the React build includes binary images, fonts, videos, or other binary files, either inline them as base64/data URLs during the build or ask for ZIP/multipart bundle support before publishing. The maximum publication payload is 100 MB. ## Roles - `viewer`: can sign in and open files shared with their email or domain. - `publisher`: can publish files, create API keys, manage recipients, and inspect access activity. - `admin`: same publishing permissions, reserved for administrative expansion. New accounts become publishers only when their email domain is configured in `PUBLISHER_EMAIL_DOMAINS`. Other accounts can register as viewers but cannot create publications or API keys. ## Access modes - `private`: only the owner can open it from the console. - `company`: any signed-in account whose email domain is configured in `PUBLISHER_EMAIL_DOMAINS` can open it. - `recipients`: only listed emails or domain targets such as `@example.com` can open it. - `signed`: specific email recipients receive a signed-access token and htmlshare records proof. - `public`: anyone with the link can open it. For `signed`, use specific email addresses only. Domain targets are valid for `recipients`, not signed legal proof. ## Getting an API key 1. Sign in with a publisher account. 2. Open the app. 3. Create an Agent key. 4. Store the `hsk_...` token in the assistant or CI secret store. The `/api/v1/ai/signup` endpoint can start publisher onboarding, but it only returns or emails keys for domains allowed by `PUBLISHER_EMAIL_DOMAINS`. If the email is external, htmlshare sends a viewer login link and rejects publishing. ## Fast publish Anonymous or no-token publishing is disabled by default on this deployment. `mode: "fast"` is only available when the server is explicitly configured with `ENABLE_FAST_PUBLISH=true`. Do not use `mode: "fast"` unless `/api/v1/publish` discovery returns `"fast_enabled": true`. ## MCP Remote MCP endpoint: ```text https://share.ecija.ai/mcp ``` For Claude remote MCP, add the endpoint above and press Connect. htmlshare advertises OAuth metadata, asks the user to sign in with Microsoft, and issues Claude a per-user OAuth bearer token. Do not use one shared token for all users. For scripts, CI, or local stdio MCP clients that cannot use browser OAuth, create a personal `hsk_...` key from `Agent keys` and configure: ```text HTMLSHARE_URL=https://share.ecija.ai HTMLSHARE_TOKEN=hsk_... ``` ## Safety Never publish secrets, credentials, private keys, tokens, raw personal data, or confidential material unless the user explicitly instructs you and the visibility is appropriately restricted.