Skip to content

Sites and onboarding

A site is the unit of installation in Sill: one site is one registered domain. Adding a site at app.sill.so mints a per-site site_key, runs a four-step onboarding flow (domain → skills → install + verify → complete), and — once domain ownership is proven — exposes that site’s signed agent card, MCP server, and ARD ai-catalog.json at Sill’s edge, all verifiable against the public JWKS.

Sites are managed in the dashboard at https://app.sill.so/. The Sites overview lists every site on your account; the Add site button opens the onboarding shell. The shell is a single-screen, four-step state machine — there are no separate routes for each step, and progress is persisted on the server so closing the tab and returning resumes where the merchant left off.

The site lifecycle is the same in both Discovery and Transactional modes; Transactional adds further gates on top of a verified site (signed mandates, policy, payment authorization), but the site itself is created and verified the same way.

flowchart LR
  A[1 - Domain<br/>add site] --> B[2 - Skills<br/>pick capabilities]
  B --> C[3 - Install + verify<br/>script tag / WordPress / Shopify]
  C --> D[4 - Complete<br/>You are live]
  D -.stale status detected.-> C

Step 1 (Domain) — the first screen after clicking Add site.

The merchant types a bare domain (e.g. example.com; the https:// prefix is implied and any path is stripped). On submit the dashboard calls POST /v1/sites, which creates the site row at status pending_proof and returns the site, its site_key, and its site_key_hash. Domain validation is a lightweight format check; deeper checks happen during install + verify, not here.

If the domain is already on your account, the dashboard surfaces a calm “resuming your existing setup” toast and jumps straight to the right step for that site, rather than erroring out.

Terminal window
curl -X POST https://api.sill.so/v1/sites \
-H "authorization: Bearer <session>" \
-H "content-type: application/json" \
-d '{"domain":"example.com","name":"Example"}'
{
"site": {
"site_id": "01J...ULID...",
"account_id": "01J...ULID...",
"domain": "example.com",
"name": "Example",
"status": "pending_proof",
"site_key": "sk_...",
"site_key_hash": "<43-char base64url SHA-256>",
"policy_version": "discovery-v1",
"edge_sync_status": "synced",
"created_at": "2026-06-22T12:00:00Z"
},
"site_key_shown_once": true
}

The raw site_key is returned once at create time; treat it as a secret embedded in the snippet. The site_key_hash (base64url(sha256(site_key)), 43 characters) is the public, URL-safe identifier used by the hash-form snippet at the edge — see Embed script.

Step 2 surfaces the seven default skills (Browse catalog, Check availability, Place order, Order status, Track shipment, Request refund, Recommend) and — when platform detection succeeds — a detection-driven suggestion panel. Detection is a hint, never a gate: a detection failure simply hides the suggestion panel and the merchant continues with the seven defaults.

Skill toggles persist per site as the merchant flips them. There is no merchant-facing “Analyze my site” button; any deeper extraction runs server-side and best-effort, and never blocks the flow.

Step 3 (Install + verify) — three install-method tabs with a shared proof-check state. The script-tag tab is the default.

The merchant picks an install method and places the Sill snippet, then proves domain ownership. The three peer tabs are:

  • Script tag — the universal path. Paste a one-line <script> into the site’s HTML; see Embed script for the snippet, sizing, and load behavior.
  • WordPress — guided paste for a WordPress theme or plugin slot.
  • Shopify — OAuth connect to the merchant’s Shopify store. On a Shopify site the OAuth grant itself proves ownership, so a separate proof panel is not shown on this tab.

Verification is mandatory. There is no skip-verify affordance: the proof check itself advances the flow. The proof channels are described in detail in Domain verification — in short:

  • HTTP challenge (script-tag / WordPress) — Sill’s origin server-fetches the merchant’s published HTML and looks for the snippet (with the per-site data-proof-token) embedded in the served page. Finding it records a P1 proof and flips the site to discovery_active. The browser/runtime does NOT transmit the proof token; the attribute exists only so the origin’s homepage scan can confirm domain ownership by finding it in the merchant-served HTML.
  • .well-known fallback — when the homepage scan misses (single-page apps, JS-rendered HTML), the merchant can host a static file under /.well-known/ instead.
  • Shopify OAuth domain-match (Shopify tab) — the OAuth callback’s verified shop domain matches the site, which records a P2 proof and (with a P1 alongside) enables Transactional gates.

The canonical snippet is built by the dashboard and looks like:

<!-- paste before </body> -->
<script async src="https://cdn.sill.so/embed.js"
data-site-key="sk_…"
data-proof-token="pf_…"></script>

The data-proof-token is per-site and opaque — public-by-design once installed. It is the ownership-proof token Sill’s origin looks for in the served HTML; it is not a bearer credential, and the embed runtime in the browser does not read or send it.

Step 4 fetches the fresh server-side status before rendering — not the cached client snapshot — so the “you’re live” hero only ever appears when the server says the site is discovery_active or transactional_active. If the merchant lands here on a still-pending_proof site (stale URL, race, forced navigation), Sill shows a safety-net face that says “One step left — verify” and routes back to step 3 instead of falsely claiming success.

The success face surfaces a condensed advert for the rest of the protocol stack with a “Notify me” interest-capture for the items that are not yet live (see Protocols for the canonical state of each).

Sites move through a small, deliberate set of states. The wire-level enum is in packages/types/src/site.ts:

statusWhat it meansDashboard card label
pending_proofSite exists, site_key minted, no proof recorded yet (tier T0).NOT YET VERIFIED
discovery_activeA first valid P1 (HTTP challenge) proof was recorded (tier T1). Audit writes enabled.AWAITING TRAFFIC then DISCOVERY · LIVE
transactional_activeAdditionally has a P2 (OAuth domain-match) proof (tier T2/T3). Mandate + connector dispatch enabled.DISCOVERY · LIVE (Transactional gates separately surfaced)
suspendedOps action only.(hidden from list)

The Sites overview also splits discovery_active into two card faces based on whether any agent traffic has been seen:

  • Awaiting traffic — verified, but last_seen_at is null. The card prompts the merchant to view the install snippet.
  • Live — verified and at least one beacon has arrived. The card shows stats and a calm DISCOVERY · LIVE label. If beacons stop arriving for more than 24 hours, a NO RECENT BEACONS band invites the merchant to re-check the install (the site_key may have rotated).

A Shopify site that auto-installed via ScriptTag but has not yet received an agent visit shows a third intermediate face: AWAITING FIRST AGENT VISIT — Sill installed the embed; recording starts on the first agent visit.

Returning to the dashboard mid-onboarding jumps to the right step based on the site’s status:

  • pending_proof → step 2 (Skills). The merchant has a site but no proof yet.
  • discovery_active / transactional_active → step 4 (Complete). The site is live; show the success hero.
  • Anything else (null, suspended) → step 1 (Domain).

Switching the active site via the dashboard’s top bar re-runs this mapping so the flow does not inherit the previous site’s step.

Removal is a two-stage modal:

  1. Stop recording (available today) — soft-delete. The embed snippet stops being recognized, the site disappears from the active list, and past audit records remain on Sill’s servers and are exportable from the Audit log’s “Show deleted sites” toggle. Re-adding the same domain creates a new site (new site_id, new chain).
  2. Erase content (in a later release) — cryptographic erasure: destroy the per-site key used to encrypt records, leaving the ciphertext undecryptable. Rendered disabled today with the explicit “available in a later release” label.

The hard-delete path is intentionally not offered: audit-chain foreign keys are ON DELETE RESTRICT, and the chain’s integrity is a product property, not a UI convenience.

Does Sill require a DNS or CNAME record to verify a site? No. Proof of ownership runs through the install snippet (HTTP challenge or .well-known fallback) or through Shopify OAuth domain-match. There is no DNS change to make. See Domain verification.

Can I add a subdomain as a separate site? Yes — a site is bound to exactly one registered domain string, and shop.example.com and example.com are distinct sites with distinct site_keys, distinct agent cards, distinct ARD catalogs, and distinct audit chains.

What changes between Discovery and Transactional onboarding? Onboarding itself is the same four steps. Transactional adds a P2 proof (OAuth domain-match) and connector configuration on top of a discovery_active site; the path is covered in the Transactional overview. Discovery is live today; the Transactional core has been validated end-to-end on the live Stripe rail at dogfood scope, with Shopify live-rail still a separate, un-flipped gate.

Is the site_key a secret? The raw site_key returned at create time is embedded in the script-tag snippet and should be treated like any other identifier scoped to the site. The site_key_hash is the public, URL-safe form used by the hash-form snippet at cdn.sill.so/embed.js?site=<hash>.

Can I rotate the site_key? Yes. The dashboard exposes a key-rotation action; re-rotating invalidates the previous key after the merchant re-installs the snippet with the new value. A site whose key was rotated but whose snippet was not updated will show the NO RECENT BEACONS band after the freshness window elapses.

  • Domain verification — the proof channels (HTTP challenge, .well-known, Shopify OAuth) in depth.
  • Embed script — the snippet, hash-form URL, and load behavior.
  • Agent card — what gets published at the edge once a site is verified.
  • ARD catalog — the signed ai-catalog.json per site.
  • Verify a signature — how a third party verifies any Sill-signed surface against the public JWKS.
  • Quickstart — the end-to-end “add a site, install the snippet, see your first agent” walkthrough.
  • Transactional overview — what changes once a site is gated for signed mandates and payment authorization.

External references: the agent card is A2A-compatible; the MCP server speaks the Model Context Protocol; the per-site signed manifests use RFC 8785 JCS canonicalization with ed25519 signatures over a JWS / EdDSA envelope; site identity uses did:web over the merchant’s verified domain.