REST API adapter
The REST adapter talks to any HTTP API that serves JSON over GET. It has two modes:
| Mode | When to use |
|---|---|
querystring | Your API accepts filters as ?field=value&field__gt=10 |
client-filter | Your API returns a full list; Spelo filters in memory |
If your API is bespoke enough that neither mode fits (e.g. requires POST, has a proprietary JSON filter DSL, uses GraphQL), use the Webhook adapter instead.
Config shape
{ "type": "rest", "config": { "baseUrl": "https://api.example.com", "auth": { "type": "bearer", "value": "${REST_API_TOKEN}" }, "queryMode": "querystring" }, "collections": { "products": { "source": "/v1/products", "searchable_fields": ["name", "description"], "filterable_fields": ["category", "price", "in_stock"], "display_fields": ["id", "name", "price"] } }}Auth modes
{ "auth": { "type": "bearer", "value": "eyJhbGc..." }}Sends Authorization: Bearer eyJhbGc... on every request.
{ "auth": { "type": "apiKey", "value": "abc123", "header": "X-API-Key" }}Sends X-API-Key: abc123 (or whatever header you specify — defaults to X-API-Key).
{ "auth": { "type": "none" }}For public APIs.
Query mode: querystring
The adapter encodes filters as Django-style query params:
| SearchParams | Query string |
|---|---|
{ field: "price", operator: "eq", value: 10 } | price=10 |
{ field: "price", operator: "gt", value: 10 } | price__gt=10 |
{ field: "price", operator: "gte", value: 10 } | price__gte=10 |
{ field: "price", operator: "lt", value: 10 } | price__lt=10 |
{ field: "price", operator: "lte", value: 10 } | price__lte=10 |
{ field: "name", operator: "contains", value: "x" } | name__contains=x |
{ field: "category", operator: "in", value: ["a","b"] } | category__in=a,b |
free-text query | q=<query> |
sort_by, sort_direction | ordering=price or -price |
limit | limit=5 |
Works out of the box with Django REST Framework, Prisma REST, PostgREST, Strapi, Directus.
Expected response shape:
{ "results": [ { "id": 1, "name": "...", "price": 10 } ], "count": 42}Or simply an array:
[ { "id": 1, "name": "...", "price": 10 }]Both are handled.
Query mode: client-filter
The adapter calls GET /v1/products with no filter params, receives the list, and filters in memory. Use this when:
- Your API doesn’t accept filter params
- The dataset is small enough to fetch entirely (< 500 items)
- You want the AI to search without your API having to implement search
Same in-memory helpers as the JSON adapter — matchesFilter, matchesQuery, sortAndLimit.
Setup
-
Confirm your API shape
Make sure
GET <baseUrl><source>returns either{ results: [...] }or a raw array. If not, pointsourceat an endpoint that does (e.g./api/v1/products.json). -
Choose auth
Bearer tokens are most common. API-key headers are fine too. If your API uses Basic Auth, use the Webhook adapter (which lets you set any headers).
-
Paste config in the dashboard
Dashboard → Data → REST API → fill in fields → Test connection.
-
Map collections
sourceis the path relative tobaseUrl. Example:baseUrl: "https://api.example.com",source: "/v1/products"→ full URLhttps://api.example.com/v1/products.
HTTPS required
The baseUrl must start with https://. The only exception is http://localhost / http://127.0.0.1 (for local dev). The adapter rejects plain HTTP to any other host.
Security notes
- Bearer tokens and API keys are encrypted at rest (AES-256-GCM).
- Adapter only ever emits
GETrequests — no POST/PUT/DELETE. - Query values are URL-encoded before concatenation. No injection path.
Troubleshooting
401→ auth misconfigured. Try the request incurlwith the same header.404→ wrong path insource.429→ hitting the API’s rate limit. Switch toclient-filtermode (fewer requests) or cache via a webhook.- Mixed content / CORS errors → shouldn’t happen; this adapter runs server-side.
More: Database connection errors.