Connect your data
By default, Spelo reads the DOM of whatever page the visitor is on. That works for brochure sites, blogs, restaurants, law firms, and landing pages.
For inventory-heavy sites — real estate, e-commerce, job boards, SaaS catalogs, listings — you’ll want to connect your database, so the AI can search, filter, and describe items that aren’t on the current page.
Pick the right adapter in 30 seconds
Where does your data live?
├─ A SaaS app you already use?│ ├─ Shopify → OAuth (1 click) /data/oauth/ or /data/shopify/│ ├─ Airtable → OAuth /data/oauth/ or /data/airtable/│ ├─ Google Sheets → OAuth /data/oauth/ or /data/google-sheets/│ └─ WooCommerce → OAuth /data/oauth/ or /data/woocommerce/│├─ A database you administer?│ ├─ Postgres → /data/postgres/ (also Neon, Crunchy, Render, RDS, Aurora, Timescale)│ ├─ Supabase → /data/supabase/ (PostgREST — or use /data/postgres/ for direct SQL)│ ├─ MySQL / Maria → /data/mysql/ (PlanetScale, Aurora MySQL)│ ├─ SQL Server → /data/mssql/ (Azure SQL, AWS RDS SQL Server)│ ├─ MongoDB → /data/mongodb/ (Atlas, self-hosted)│ └─ Firestore → /data/firebase/ (Cloud Firestore via service account)│└─ Something custom? ├─ REST endpoint you control → /data/rest/ ├─ Python / Go / Rails / PHP → /data/webhook/ (~30 min) └─ Max performance or weird tech → /data/custom-adapter/ (~2 hr, TypeScript)All 14 adapters
How it works
When the AI decides to run a search (e.g. visitor says “show me 2-bedroom apartments in Hollywood under $3k”), it calls the search_database tool. The widget forwards the call to Spelo’s API, which forwards it to your backend through an adapter.
Browser ──▶ api.spelo.ai ──▶ Your DB (via adapter) │ ▼ read-only SELECTEvery adapter implements the same interface (search, testConnection, optional describeSchema). The AI doesn’t know or care which adapter is underneath — it gets structured results back in a uniform shape.
The config shape
Every adapter is configured the same way in the dashboard (or in adapter.config.json if self-hosting):
{ "type": "postgres", "config": { "connectionString": "postgresql://readonly:pass@host:5432/dbname", "ssl": true }, "collections": { "properties": { "source": "listings", "searchable_fields": ["address", "city", "description"], "filterable_fields": ["beds", "baths", "price", "city", "amenities"], "display_fields": ["id", "address", "city", "beds", "baths", "price"], "max_limit": 10, "description": "Rental listings available in the next 30 days" } }}type— one of the 14 adapter types listed aboveconfig— adapter-specific connection details (encrypted at rest)collections— logical groups the AI can query. The key (properties) is the name the AI uses;sourceis the actual table / sheet / endpoint name.
See the Sites API reference for the full TypeScript definition.
Security defaults
See Security for the full threat model.
Test before you ship
Every adapter has a testConnection method. From the dashboard:
- Fill in the config
- Click Test connection
- The API runs a cheap ping (
SELECT 1,db.admin().ping(),GET /etc.) and reports back - Green check → you’re good. Red error → exact failure reason, with link to the troubleshooting page
If a test fails, see Database connection errors.
Schema introspection (optional)
Most adapters can introspect your backend and describe the available fields to the AI automatically — so you don’t have to enumerate every field by hand. See Schema introspection.
What if my data source isn’t listed?
Two paths:
Common questions
Will the AI make up answers if the database returns nothing? No — the system prompt instructs the AI to say so when results are empty. If you’re seeing hallucinated answers, see Slow responses for diagnosis (often the adapter is timing out and the AI falls back to DOM context).
Can I connect more than one adapter to the same site?
Yes. Up to 5 adapters per site on Pro+. The AI picks the right one based on the description you give each collection.
What about write operations (book this, order that, submit a form)?
Spelo’s adapters are read-only by design. For voice-driven actions, see Tools & function calls — fill_field and click_element operate on the DOM, and a custom webhook tool can route to your backend’s POST endpoint with end-user confirmation.